.NET Code Reuse presentation

Tomorrow, I’ll be doing a presentation on .NET code reuse across Silverlight, WPF and Windows Phone at the LA SLUG user group meeting.

Microsoft has been touting for a while that you can reuse your code across these platforms, but never really tell you about all the gotcha’s. As part of my day job building the ArcGIS API for Silverlight, WPF and Windows Phone (where 99% of the code is reused), I’ll talk about the experiences and lessons learned, and what usually hides in the remaining 1%.

The meetup will take place:
Wednesday, May 25, 2011 at 7:00 PM (PDT)
United Future / Wongdoody
8500 Steller Dr Culver City, CA

If you are not in the LA Area, you will miss out on the free beer and pizza, but for the first time ever LA SLUG will be streaming the event online. See event details for more info. I’ll post slides (and if there is a recording, a link to that as well) shortly after.

Silverlight vs. WPF

Silverlight or WPF? Who will win? Or will they team up to be the best tigerblood-powered kick-ass platform ever conceived?

ESRI DevSummit 2011–over'n'out

The ESRI Developer Summit is over, and I had quite a blast. We got tons of great feedback and tough questions from all the developers attending. Thank you for that! We also had some well-attended sessions on Windows Phone, Silverlight and WPF. When these recordings goes live, I’ll update this blog-post.

For the first time, I even got to go on stage during plenary and make a fool of myself. You might already have read about my ventures into programming with a Kinect, but I got to show a far more polished version during the plenary session, and luckily everything worked out great. This version (although not demoed due to time constraints) actually supports multiple users interacting with the map at the same time (at one point we had 4 different people drawing on the map all simultaneously). For those interested, this was based on OpenNI drivers and the ArcGIS API for WPF, which is a different approach than I originally blogged about. Here’s a recording of my 2 minutes of “fame” Smile:

Me on stage making a fool of myself

I have to admit I was a little nervous this would break down during the demo, since this was all based on stuff that wasn’t even in beta software yet. We later had it running at our showcase area 24/7 and I didn’t have to restart the app for almost 3 days running with lots of users playing with it, so perhaps it was running more solid than I had feared Smile - So go play with those OpenNI drivers! They might be called “unstable” but I found them to be very stable.

My little A-to-B app also go a nice mention during the plenary. I wrote this to learn some more phone application practices, exercise the phone API we’ve been working on for a while and simply to have some coding fun. If you have a Windows Phone 7, go download it now, and if not, here’s Dave giving a quick tour of the app.

A-to-B WinPhone7 Application demoed

Thank you to every who attended and especially those who gave us feedback.

Fun times with Kinect and WPF

I recently bought a Kinect controller for my Xbox and is really loving it. Of course I had to see if I couldn’t use that for something, and after some other people were nice enough to create and release free Windows drivers and libraries, I had to try it!

I started out with Code Laboratories “CL NUI Platform” which is a simple installer that installs the drivers and some libraries. It also comes with some samples showing how to connect to the sensor.

I quickly got that going, with a small app that displays the RGB and Depth image from the sensor.

223324934[2]

“Unfortunately” this is also all you get out of the box. If you expect to automatically get an event when you wave your hand or doing some other gesture, this is not for you. However if have a little love for some simple Image Analysis algorithms, you should be all over this too!

I wanted to make a simple gesture API that could tell me when a user drags, pinch/stretch or flicks something, very similar to what you do with a Touch Screen. So basically an API that mimics an invisible touch screen hanging suspended in the air. Luckily the algorithms for this turned out to be pretty simple.

The first thing you do is go through the depth image pixel by pixel. If you find a pixel that is too close or too far away, replace it with Color.Empty so we can ignore those. That we we will only “see” things in the picture that are within a certain distance from the sensor. Like for instance two hands stretched out. This leaves us with a set of pixels that could potential be some stretched out hands.

223411798[2]

We need to associate these pixels with each other. Let’s say all pixels that are next to each other that are not transparent, belong to the same hand. We call these sets of grouped pixels for “Blobs” and there’s a nice simple algorithm for detecting all the blobs in an image, known as “Connected Component Labelling”. Instead of explaining how it works here, all you need to know is here on wikipedia. If you register their center and size, you can easily use these as “touch input” and discard too large or small blobs. This is what this looks like, using a circle for center and size of each blob:

30 times a second you will be calculating a new set of blobs. Compare these to the previous blobs, and use the center and size to see which blobs are the same and has moved, which are new, and which disappeared. If I only have one blob and it moves, I consider this a “drag”. If I have more than 1, I calculate the bounding box of all the blobs, measure its diagonal and compare it to the size of the previous diagonal - The fraction between these two diagonals is the scale in a pinch or stretch.

Now all we need to do is take these “gesture events” and hook them up to something. Like for instance a map. So here’s the end-result: (note : It looks a little jerky because of the screen capture software, but it runs a lot smoother when not recording and flicks works consistently).

Minority MapReport

It worked surprising well for a first go.

Download source: Sorry no source available at this time, due to some licensing restrictions.

Submitted my first WinPhone 7 Application

imageI’ve just submitted my first application to the Windows Phone Marketplace. It’s a very simple app that creates a “Guide Post” with signs on a pole showing distances and direction to any point in the world. You have probably seen these at various sites all over the world, or in the TV Show “M*A*S*H”.

It’s all built in Silverlight, and uses PlaneProjection to give give the signs a 3D effect. You use your finger to slider over the screen to rotate it.

In addition to that there’s a Map where you can view your current location and the great circle line (ie. shortest path) between you and the points of interest. This is of course using the ESRI ArcGIS API for Windows Phone that we just released.

Below is a few screenshots and a video clip of the app in action.

screen_12-1-2010_8.51.30.996screen_12-1-2010_8.50.48.336
screenshot_12-2-2010_12.26.46.864screenshot_12-2-2010_12.27.59.830

GuidePost Screen Capture

It was a great fun little app to build and only took a few evenings to get done. You can download the app to your phone from this link: http://bit.ly/WP7GP

ESRI ArcGIS Silverlight/WPF API released

Last week we finally released v1.0 RTW of our Silverlight/WPF API. Today at our User Conference in San Diego, Jack Dangermond announced, that it even will be free for non-commercial use. The API will run on both v2 and v3 of Silverlight.

Furthermore today we released the entire source code for the toolkit assembly on CodePlex: http://esrisilverlight.codeplex.com

Also today at the Windows Partner Conference, we announced MapIt, a mapping solution running on a combination of SQL Server 2008, IIS and Silverlight/WPF and also with integration into Sharepoint. You can download a free 60-day evaluation of MapIt today. I encourage you to go see some of the demonstration videos – especially if you are new to GIS, this video could be an eye-opener to what information is hidden in your existing business intelligence.

If you are at the ESRI User Conference this week, come by the Silverlight Island in the showcase area and talk some Silverlight. I’ll be there most of the time Tuesday through Thursday. I’ll also be joining Rex Hansen and Art Haddad at the .NET SIG Tuesday evening, and the Silverlight intro sessions Wednesday and Thursday. Also watch Rich’s Demo Theater session which will demonstrate the ESRI Map Web Part for SharePoint and MapIt (the title on this session is incorrect).

Parsing a GeoRSS Atom feed using XML to LINQ in Silverlight

…or how to put a map of your blogposts on your blog.

I recently started a little pet project with a “photo a day” blog. I thought it could be fun to geocode each blogpost with to the place where each photograph was taken, and then place each photo on a map, similar to the flickr map I created earlier.

The most common way of geocoding an atom feed, is by adding a <georss:point>[latitude] [longitude]</georss:point> field for each entry. However, the blogengine I’m using currently doesn’t support that, so I will also try and find the location using a magic string in the blogpost, in this case “Location: [latitude] [longitude]”. You will notice that the posts I made so far, all have this at the end of the post. This might not be the most elegant solution to geocoding your blogposts, but it should work for any type of blog.

So the first step is to create a WebRequest that will download the feed (this could be simplified by using the WebClient, but I like the full control of the WebRequest):

System.Net.WebRequest request = System.Net.WebRequest.Create(
     new Uri("http://socaldaily.sharpgis.net/syndication.axd?format=atom", UriKind.Absolute));
request.BeginGetResponse(new AsyncCallback(createRssRequest), new object[] { request, this });

Begin get response handler:

private static void createRssRequest(IAsyncResult asyncRes)
{
      object[] state = (object[])asyncRes.AsyncState;
      System.Net.HttpWebRequest httpRequest = (System.Net.HttpWebRequest)state[0];
      Page page = (Page)state[1];
 
      if (!httpRequest.HaveResponse) { return; }
 
      System.Net.HttpWebResponse httpResponse = (System.Net.HttpWebResponse)httpRequest.EndGetResponse(asyncRes);
      if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK) { return; }
      Stream stream = httpResponse.GetResponseStream();
      page.Dispatcher.BeginInvoke(() => { page.ParseAtomUsingLinq(stream); });
}

When the request comes back, it will call our ParseAtomUsingLinq method with the response stream. The LINQ expression will select basic parameters like title, date, link, contents and if available, the georss location point.

private void ParseAtomUsingLinq(System.IO.Stream stream)
{
    System.Xml.Linq.XDocument feedXML = System.Xml.Linq.XDocument.Load(stream);
    System.Xml.Linq.XNamespace xmlns = "http://www.w3.org/2005/Atom"; //Atom namespace
    System.Xml.Linq.XNamespace georssns = "http://www.georss.org/georss"; //GeoRSS Namespace
 
    //Use LINQ to select all entries
    var posts = from item in feedXML.Descendants(xmlns + "entry")
                select new 
                {
                    Title = item.Element(xmlns + "title").Value,
                    Published = DateTime.Parse(item.Element(xmlns + "updated").Value),
                    Url = item.Element(xmlns + "link").Attribute("href").Value,
                    Description = item.Element(xmlns + "summary").Value,
                    Location = fromGeoRssPoint(item.Element(georssns + "point"))  //Simple GeoRSS <georss:point>X Y</georss.point>
                };
     foreach (var post in postsOrdered)
     {
          ESRI.ArcGIS.Geometry.MapPoint point = null;
          if (post.Location != null)
          {
               point = post.Location; //Use GeoRSS location
          }
          else
          {
               point = ExtractLocation(post.Description); //Search for location in blog content
          }
          if (point == null) continue; //We didn't find a point
          string imageSrc = ExtractImageSource(post.Description, post.Url); //try and find an image to use for symbol
          //TODO: Add points to map...
     }
}

You will notice in the above code we use three utility methods for extracting data. First we have a method that converts the simple GeoRSS format “<georss:point>X Y</georss.point>” to a point. In this case I’m using the MapPoint class from the ESRI ArcGIS Silverlight API, since I wan’t to use that to draw my entries on the map.

private ESRI.ArcGIS.Geometry.MapPoint fromGeoRssPoint(System.Xml.Linq.XElement elm)
{
    if (elm == null) return null;
    string val = elm.Value;
    string[] vals = val.Split(new char[] { ' ' });
    if (vals.Length != 2) return null;
    double x = double.NaN;
    double y = double.NaN;
    if (double.TryParse(vals[1], out x) && double.TryParse(vals[0], out y))
    {
        return new ESRI.ArcGIS.Geometry.MapPoint(x, y);
    }
    return null;
}

If this doesn’t return any results (usually if the feed is not georss enabled), we will during the loop look for the location tag in the entry content, using the following helper method:

private ESRI.ArcGIS.Geometry.MapPoint ExtractLocation(string description)
{    
    int idx = description.LastIndexOf("Location: ");
    int idx2 = description.LastIndexOf("</p>");
    double x = double.NaN;
    double y = double.NaN;
    if (idx < idx2 && idx > -1)
    {
        string sub = description.Substring(idx, idx2 - idx);
        string[] vals = sub.Split(new char[] { ' ' });
        foreach (string val in vals)
        {
            if (val[0] == 'N')
            {
                double.TryParse(val.Substring(1), out y);
            }
            else if (val[0] == 'S')
            {
                if (double.TryParse(val.Substring(1), out y)) y *= -1;
            }
            else if (val[0] == 'E')
            {
                double.TryParse(val.Substring(1), out x);
            }
            else if (val[0] == 'W')
            {
                if (double.TryParse(val.Substring(1), out x)) x *= -1;
            }
        }
        if (!double.IsNaN(x) && !double.IsNaN(y))
        {
            return new ESRI.ArcGIS.Geometry.MapPoint(x, y);
        }
    }
    return null;
}

Lastly, we will search for the first <img src=”…”/> entry in the body and use that for displaying the entries on the map:

private string ExtractImageSource(string description, string feedlink)
{
    int idxSrc = description.IndexOf("<img ");
    if (idxSrc >= 0)
    {
        int idxSrc2 = description.Substring(idxSrc).IndexOf("src=\"");
        int idxSrc3 = description.Substring(idxSrc + idxSrc2 + 5).IndexOf("\"");
        if (idxSrc2 >= 0 && idxSrc3 >= 0)
        {
            string src = description.Substring(idxSrc + idxSrc2 + 5, idxSrc3);
            Uri uri = new Uri(src, UriKind.RelativeOrAbsolute);
            if (uri.IsAbsoluteUri) return uri.AbsoluteUri;
            Uri page = new Uri(feedlink, UriKind.Absolute);
            return new UriBuilder(page.Scheme, page.Host, page.Port, src).Uri.AbsoluteUri;
        }
    }
    return null;
}

In our feed entries loop, we can now simply construct a graphic, set a few attributes that we will use for binding the look for the symbol (ie title and image) and add it to our graphics layer. The symbol I use here is the same as used for the flickr application mentioned above.

ESRI.ArcGIS.Graphic g = new ESRI.ArcGIS.Graphic()
{
    Geometry = point,
    Symbol = myFeedSymbol
};
g.Attributes.Add("Title", title);
g.Attributes.Add("ImageURI", src);
g.Attributes.Add("WebURI", link);
myGraphicsLayer.Graphics.Add(g);

You can view the blog map in action here: http://socaldaily.sharpgis.net/page/Photo-map.aspx

Note that there are several ways to geocode blogposts, and this approach only deals with the simplest version.

ESRI ArcGIS Silverlight/WPF API released

FINALLY we released the beta of our new ArcGIS client API for Silverlight and WPF the end of this week.

You can download the beta here, where you also can find links to documentation and samples. Note that the download requires an ESRI global account, which you can create for free.

Art has the details on his blog.

This his has been (well still is since it's beta :-) a great fun project to work on. We tried to design it to be similar to our JavaScript and Flex APIs, but at the same time make it more ".NET" when it made sense, or taken advantage of capabilities Silverlight had. We really look forward to the feedback from you, as well as talking to anyone who's at the ESRI Developer summit next week. I'll be there Monday through Thursday, mostly hanging out at the showcase area, so if you're there, stop by say hi and get to see the API first hand. Art and Rex will be doing an intro session Wednesday at 1pm, and I'll join them Thursday 10:15am for the advanced session.

Below is a simple flickr application that I created for the api, (source is available for download at the code gallery). Just zoom to any area of interest, hit the flickr button, and images in that area pops up. The sample demonstrates the power of templating the symbols which allows you to associate animations to states of the symbols, as well as using binding. This is really no different than the states model used in other Silverlight controls. The flickr symbols here has two states: MouseOver, which zooms the image and displays a small description at the bottom. The result box to the left uses the selection state when you hover on the features to first scale the image slightly and highlight the border, and if you stay hovering on it, will expand to full size. Click the result to center on that feature.