Author Topic: Integrating weather data using PhotoFusion  (Read 4637 times)

aolney

  • Newbie
  • *
  • Posts: 1
    • View Profile
Integrating weather data using PhotoFusion
« on: June 04, 2010, 11:01:23 AM »
I'm planning on using TopoFusion for search and rescue dogs with the Garmin Astro collar.

Search dogs' ability to find victims is influenced by weather conditions. Therefore I'd like a weather "overlay" for trails. This is particularly relevant for changes in wind direction.

My plan is to use the Weather Underground API to pull weather data at regular intervals, e.g. 30 seconds to a minute, and then programmatically create jpegs with formated text information (black letters on white background). This should let me run my own program alongside TopoFusion and provide TopoFusion with data it can ingest via PhotoFusion.

My question is the following. When my team trains, we might have a half dozen or so members in the field at once. Will PhotoFusion have a problem with this, i.e. the situation where there are >1 GPS tracks at a given time, but only one image/weather data to share between them?

BTW a great feature for TopoFusion would be a custom waypoint annotator that ingests e.g. csv and displays this way, so that converting to an image would be unnecessary.


----------------

OK, update. Here is one of the images I'm producing.

I decided to use Yahoo's API rather that WU b/c the API is cleaner, has all the data I care about, and seems to be updated more regularly.

When I write the jpg, I'm reading it back in and modifying its exif data I assume that exif's date taken is the right parameter to set.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Net;
using System.Data;

namespace WeatherToPhotoFusion
{
    public class YahooWeather
    {

        public string WindSpeed { get; set; }
        public string WindDirection { get; set; }
        public string Humidity { get; set; }
        public string Pressure { get; set; }
        public string PressureDirection { get; set; }
        public string Temperature { get; set; }
        public string WeatherCondition { get; set; }
        public string PublishedTime { get; set; }
        public DateTime ReceivedTime { get; set; }

        public YahooWeather() { }


        public static YahooWeather GetConditions(string location)
        {
            YahooWeather conditions = new YahooWeather();

            XmlDocument xmlConditions = new XmlDocument();
            xmlConditions.Load(string.Format("http://weather.yahooapis.com/forecastrss?w={0}", location));

            // Set up namespace manager for XPath 
            XmlNamespaceManager ns = new XmlNamespaceManager(xmlConditions.NameTable);
            ns.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0");

            // Get forecast with XPath 
            XmlNode node = xmlConditions.SelectSingleNode("/rss/channel/yweather:wind", ns);

            conditions.WindSpeed = node.Attributes["speed"].InnerText;
            conditions.WindDirection = node.Attributes["direction"].InnerText;

            node = xmlConditions.SelectSingleNode("/rss/channel/yweather:atmosphere", ns);

            conditions.Humidity = node.Attributes["humidity"].InnerText;
            conditions.Pressure = node.Attributes["pressure"].InnerText;

            switch (node.Attributes["rising"].InnerText)
            {
                case "0": conditions.PressureDirection = "steady";
                    break;
                case "1": conditions.PressureDirection = "rising";
                    break;
                case "2": conditions.PressureDirection = "falling";
                    break;
            }

            node = xmlConditions.SelectSingleNode("/rss/channel/item/yweather:condition", ns);

            conditions.WeatherCondition = node.Attributes["text"].InnerText;
            conditions.Temperature = node.Attributes["temp"].InnerText;

            node = xmlConditions.SelectSingleNode("/rss/channel/item/pubDate", ns);

            conditions.PublishedTime = node.InnerText;
            conditions.ReceivedTime = DateTime.Now;

            return conditions;
        }

    }
}
     
---------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace WeatherToPhotoFusion
{
    public class TextJPEG
    {
        public TextJPEG() {}

        public static void WriteFile( YahooWeather yahooWeather)
        {
            int width = 400, height = 400;

            SolidBrush backgroundColor = new SolidBrush(Color.White);
            Font font = new Font("Arial", 12,FontStyle.Bold );

            System.Drawing.Bitmap bitmap = new Bitmap(width,height);
            System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);
           
            graphics.FillRectangle( backgroundColor , 0, 0, width, height);

            double radian = int.Parse(yahooWeather.WindDirection) * Math.PI / 180;

            TextJPEG.DrawPolygon(5f, 200, Color.Red, (float)radian, graphics);
           
            graphics.DrawString("Temperature:\t\t"+ yahooWeather.Temperature, font, SystemBrushes.WindowText, new Point( 10, 10 ) );
            graphics.DrawString("Pressure:\t\t"+ yahooWeather.Pressure, font, SystemBrushes.WindowText, new Point(10, 50));
            graphics.DrawString("PressureDirection:\t"+ yahooWeather.PressureDirection, font, SystemBrushes.WindowText, new Point(10, 100));
            graphics.DrawString("Humidity:\t\t"+ yahooWeather.Humidity, font, SystemBrushes.WindowText, new Point(10, 150));
            graphics.DrawString("WindSpeed:\t\t"+ yahooWeather.WindSpeed, font, SystemBrushes.WindowText, new Point(10, 200));
            graphics.DrawString("WindDirection:\t\t"+ yahooWeather.WindDirection, font, SystemBrushes.WindowText, new Point(10, 250));
            graphics.DrawString("WeatherCondition:\t"+ yahooWeather.WeatherCondition, font, SystemBrushes.WindowText, new Point(10, 300));
            graphics.DrawString("PublishedTime:\t\t"+ yahooWeather.PublishedTime, font, SystemBrushes.WindowText, new Point(10, 350));

           
            bitmap.Save("TEMP", ImageFormat.Jpeg);

            //strangely we have to save this to get any property items to work with

            Image image = Image.FromFile("TEMP");
            PropertyItem[] items = image.PropertyItems;

            PropertyItem property = items[0]; //any property will do b/c we don't have a constructor
           
            string dateTimeString = yahooWeather.ReceivedTime.ToString(@"yyyy\:MM\:dd HH\:mm\:ss");
            byte[] Data = Encoding.UTF8.GetBytes(dateTimeString + '\0');
            property.Id = 0x9003;
            property.Type = (Int16) 2;
            property.Value = Data;
            property.Len = Data.Length;
            image.SetPropertyItem(property);

            image.Save( yahooWeather.ReceivedTime.ToLongDateString().Replace(" ","_")+ "_"+
                yahooWeather.ReceivedTime.Ticks.ToString() + ".JPG");
        }

        private static void DrawPolygon(float fThickness, float fLength, Color color,
                    float fRadians, Graphics graphics)
        {
            float fCenterX = 200, fCenterY = 200;

            PointF A = new PointF((float)(fCenterX +
                     fThickness * 2 * System.Math.Cos(fRadians + Math.PI / 2)),
                     (float)(fCenterY -
                     fThickness * 2 * System.Math.Sin(fRadians + Math.PI / 2)));
            PointF B = new PointF((float)(fCenterX +
                     fThickness * 2 * System.Math.Cos(fRadians - Math.PI / 2)),
                    (float)(fCenterY -
                    fThickness * 2 * System.Math.Sin(fRadians - Math.PI / 2)));
            PointF C = new PointF((float)(fCenterX +
                     fLength * System.Math.Cos(fRadians)),
                     (float)(fCenterY -
                     fLength * System.Math.Sin(fRadians)));
            PointF D = new PointF((float)(fCenterX -
                     fThickness * 4 * System.Math.Cos(fRadians)),
                     (float)(fCenterY +
                     fThickness * 4 * System.Math.Sin(fRadians)));
            PointF[] points = { A, D, B, C };
            graphics.FillPolygon(new SolidBrush(color), points);
        }
    }
}
« Last Edit: June 04, 2010, 10:13:11 PM by aolney »

ScottMorris

  • Administrator
  • Sr. Member
  • *****
  • Posts: 2754
  • TopoFusion Author
    • View Profile
    • http://www.topofusion.com/diary
Re: Integrating weather data using PhotoFusion
« Reply #1 on: June 15, 2010, 10:27:33 AM »
Very interesting idea.  Getting some weather data into TF would be a great feature.  I will have to look at an API or two.

Doing it through PhotoFusion like you describe is not a bad idea.  The 'dateTaken' EXIF parameter should be the correct one, yes.

Shouldn't be any problem with using the same image(s) with multiple tracks. 

Rather than TF pulling CSV files, having it pull weather info directly from Yahoo or WU would seen well worth the effort.  Can you get historical data with Yahoo?  (i.e. from years back)

Thanks for the post.
Scott Morris - founder and co-author of TopoFusion
email: smorris@topofusion.com