Virtual Earth PhotoMap

There are many things that you can do with geographic information, amongst others you can use them to organize your data. A very typical scenario might be the organisation of your own digital photos. Usually you will have a folder-structure like the one shown below:

image

The images are structured in folders and have some unique names which don’t tell you anything about where they have been taken and what they show. To find the pictures from your last vacation in Rome you first need to know when you have been there and then you navigate your way through the folder structure. Wouldn’t it be great if you can just explore your images on a map? To navigate to a city and find all the photos you ever made there?

Well, this concept is not really new. You find lots of nice photo-sharing sites which have integration with maps like Pikeo or PlanetEye.

image

While all these sites are really great, some may want to have there own branded solution or only want to have their own photos on the map.

I was looking for a nice way to integrate a photo-viewer with Virtual Earth and came across a wonderful Silverlight-application Slide.Show which has been developed by Vertigo Software and is available including source code on Codeplex. I just had to marry it with Virtual Earth.

The idea is, to show the locations where I created photos on a map and in the infobox of each pushpin I want to have Slide.Show with the photos of this location.

image 

So, how can can we get there? Let’s start with the Slide.Show-part. Slide.Show is very easy to handle. We basically have a HTML-document which references in the header 2 JavaScripts that come with the application. In the body-element of the document we create another script which points to an XML-file with the configuration for our slide-show.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Photo-Viewer</title>
    <script type="text/javascript" src="../JS/Silverlight.js"></script>
    <script type="text/javascript" src="../JS/SlideShow.js"></script>
</head>
<body>
    <script type="text/javascript">
        new SlideShow.Control(new SlideShow.XmlConfigProvider({ url: "RomeConfig.xml" }));
    </script>
</body>
</html>

In the config-file we basically list the modules we want to use, as well as the transitions and the location for the data-file. For a full reference it is best to explore the Slide.Show-samples that come with the download.

<?xml version="1.0" encoding="utf-8" ?>
<configuration width="100%" height="100%" background="Silver">
  <modules>
    <module type="SlideViewer" />
    <module type="ProgressBar" />
    <module type="SlideDescription" />
    <module type="NavigationTray" />
  </modules>
  <transitions>
    <transition type="FadeTransition" name="CrossFadeTransition" />
    <transition type="WipeTransition" name="WipeRightTransition">
      <option name="direction" value="Right" />
    </transition>
  </transitions>
  <dataProvider type="XmlDataProvider">
    <option name="url" value="RomeData.xml"></option>
  </dataProvider>
</configuration>

In the data-file we can optionally set a title and description for each photo as well as the path to the photo (mandatory) and it’s thumbnail (optionally).

<?xml version="1.0" encoding="utf-8" ?>
<data transition="CrossFadeTransition">
  <album
        title="Rome"
        description="A few days off"
        image="../SlideShow/20080313/t/CIMG1850.JPG">
    <slide
            title="Coliseum"
            description="13/03/2008"
            image="../SlideShow/20080313/CIMG1850.JPG"
            thumbnail="../SlideShow/20080313/t/CIMG1850.JPG" />
    <slide
            title="Coliseum"
            description="13/03/2008"
            image="../SlideShow/20080313/CIMG1856.JPG"
            thumbnail="../SlideShow/20080313/t/CIMG1856.JPG" />
  </album>
</data>

aa

Hey, that’s already it. There is even a tool which allows you to generate the data-file and the thumbnails even easier. It has been created by Ben Hoffman and you will find it on Codeplex as well.

image

Next let’s have a look at the Virtual Earth part. The HTML-document contains no surprises.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>My Photo-Map</title>
    <link href="CSS/MyStyles.css" rel="stylesheet" type="text/css" />
    <script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6&mkt=en-gb" type="text/javascript"></script>
    <script src="JS/MyScript.js" type="text/javascript"></script>
</head>
<body>
    <div id="divMap" style="position:absolute; top:5px; left:5px; width:300px; height:300px;"></div>
</body>
</html>

In the style-sheet which is referenced from our HTML-document we set the size of the infobox to something that is more appropriate for photos:

.customInfoBox-previewArea 
{
    width:530px;
    height:480px;
}

Looking at the JavaScript you’ll find that we import an GeoRSS-feed. This makes it easy to add more photo-albums later on.

window.onload = GetMap;
window.onresize = Resize;

//Map
var map = null;
var mapWidth = null;
var mapHeight = null;

//VEShapeLayer
var slPhotos = new VEShapeLayer();

function GetMap()
{
    map = new VEMap('divMap');

    //Load and resize the map
    map.LoadMap();
    Resize();

    //Set Title for VEShapeLayer
    slPhotos.SetTitle('slPhotos');

    //Load Photo-Feed
    var layerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, './GeoRSS/Photos.xml', slPhotos);
    map.ImportShapeLayerData(layerSpec, onFeedLoad);
}

//Resize map and controls whenever the size of the browser window changes
//Also load the minimap
function Resize()
{
    var mapDiv = document.getElementById("divMap");
    var windowWidth = document.body.clientWidth;
    var windowHeight = document.body.clientHeight;
    mapWidth = windowWidth - 10;
    mapHeight = windowHeight  - 10;
    mapDiv.style.width = mapWidth + "px";
    mapDiv.style.height = mapHeight + "px";
    map.Resize(mapWidth, mapHeight);
    map.ShowMiniMap(mapWidth-205, 13, VEMiniMapSize.Large);
}

function onFeedLoad(layer)
{
    var numShapes = layer.GetShapeCount();
    
    map.ClearInfoBoxStyles();
    for(var i=0; i < numShapes; ++i)
    {
        var s = layer.GetShapeByIndex(i);
        s.SetCustomIcon('./IMG/Camera.png');
    }    
}

And here is now the GeoRSS-feed. Basically we just put the complete Slide.Show-application via iFrame-into the description-part of the infobox.

<?xml version="1.0" ?>
<rss version="2.0" xmlns:georss="http://www.georss.org/georss" >
  <channel>
    <title>My Photo-Map</title>
    <description>Photo-Map using Virtual Earth and Slide.Show</description>
    <item>
      <title>Rome</title>
      <description>
        <![CDATA[<iframe src="./SlideShow/Rome.htm" width="100%" height="95%"></iframe>]]>
      </description>
      <georss:point>41.890237 12.492325</georss:point>
    </item>
  </channel>
</rss>

That’s it, now you have for own photo-map but let’s take it a step further and also integrate some MSR HD View panoramas as mentioned earlier on my blog. Once this is done you have your interactive Slide.Show powered by Silverlight and your own panoramas powered by MSR HD View combined with Virtual Earth.

image

You can find the complete sample application on my SkyDrive (see below) but please note: there is a 360 degree panorama of the Pantheon in it so the file is ~22 MB big.

Advertisements
This entry was posted in Virtual Earth. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s