This post is a little technical, so my apologies. The intent is to illustrate the ease of developing extensions to TrueNorth to support geospatial standards.
So yesterday I was doing some research on the “scheme” (commonly know as the “protocol”) portion of a URL. Most of you are familiar with the http or https in an url. Also common is ftp and perhaps file. This indicates to a web browser what protocol to use when “fetching” the resource that a URL (Uniform Resource Locator) refers to. But did you know there are a whole slew of other protocols as well?
There’s a table of schemes recognized as standards, and in that table I discovered RFC5870, also known as the GeoURI standard.
GeoURI is a really simple, concise way of encoding a physical location, represented as a set of geographic coordinates, in an URL. Unlike links like Google Maps and Google Earth generate, these URLs are an application independent way of representing a location as an URL. I decided to add support for these to TrueNorth.
Under Windows, any application can register to be a protocol handler. After registration, the application is called with the URL on the command line. This is how your system, currently decides whether Internet Explorer, Firefox, Chrome or some other browser will handle a clicked link.
When TrueNorth is called with an URL on the command line, it looks through all plugins for one that implements the IProtocolHandler interface, with a Protocol property that matches the scheme in the url. When one is found, the plugin is called. In TrueNorth, the plugin pans the map in the currently open window to the given location.
To illustrate, the code to implement the plugin is presented below.
using System; using System.IO; using System.Windows.Forms; using BlueToque.Utility; using Microsoft.Win32; using TrueNorth.Data; using TrueNorth.Geographic; using TrueNorth.Interfaces; using TrueNorth.Interfaces.Plugin; using TrueNorth.PluginLib; namespace TrueNorth.Tools.Plugins { public class GeoURIHandler : PluginBase, IPlugin, IProtocolHandler { /// <summary> /// When the plugin is initialized, register the protocol handler /// </summary> /// <param name="controller"></param> public override void Initialize(IController controller) { base.Initialize(controller); // Geo URI: // http://en.wikipedia.org/wiki/Geo_URI // http://tools.ietf.org/html/rfc5870 // http://geouri.org/ // looks like this: geo:37.786971,-122.399677;;u=35;crs=Moon-2011 // u = uncertainty // crs = coordinate reference system TrueNorth.Common.Helpers.RegisterProtocolHandler( "geo", Path.GetFileName(Application.ExecutablePath), "URL:GeoURI", Application.ExecutablePath, "", Registry.CurrentUser); } /// <summary> /// Tell the world what protocol you handle /// </summary> public string Protocol { get { return "geo:"; } } /// <summary> /// Handle the GeoURI by panning the current active map to the given location /// </summary> /// <param name="argument"></param> public void Handle(string argument) { try { // get the current active map IMap map = Controller.Maps.Active; // If the map is null, create a new map using the default template if (map == null) map = Controller.OpenMap(Paths.Expand(Configuration.Current.Settings.Templates.First)); // find the form the map is in IMapForm form = Controller.FindWindow(map); if (form == null) return; // process the arguments string[] arguments = argument.Replace(Protocol,"").Split(';'); // parse the coordinate GeographicCoordinate coordinate = new GeographicCoordinate(); if (!GeographicCoordinate.TryParse(arguments[0], out coordinate)) { Controller.DisplayError(string.Format("Error parsing coordinates: \r\n{0}", argument),null); return; } form.PanTo(coordinate); } catch (Exception ex) { Controller.DisplayError( string.Format("Error handling GeoURI protocol:\r\n {0}",argument), ex); } } } }