Recent Blog Posts RSS
ViaWindowsLive on Via Virtual Earth Blog
The new ViaWindowsLive community site has launched and features not only a definitive set of resources on all Live Services from Microsoft but also a special section on Virtual Earth including a new site gallery for you to upload your sites, new articles on Version 6, including getting started guide, an interactive quick guide, location finder and more. Subscribe to the VWL aggregated blog to stay in touch with everything Live Services related. Find all the great content from this site and much, much more. Explore how other Live Services can compliment Virtual Earth and your applications.
Version 5 URL changed - Error: 'VEMap' is undefined on Via Virtual Earth Blog
It has been reported that the old url to access the Version5 javascript for Virtual Earth no longer works. This is effecting sites worldwide.
The correct way to reference the Version 5 javascript is:
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5"></script>
If you have been effected a forum thread has been started here
Silverlight Virtual Earth viewer on Via Virtual Earth Blog
With the launch of silverlight yesterday I was digging around and found this viewer for Virtual Earth by Greg Schechter. It does use the 1.1 alpha of silverlight. It gives some interesting ideas for where Virtual Earth could be headed. Certainly the demo of the performance of silverlight compared to javascript for processing showed a significant increase. This could be very useful.
And of course on the gamer front check this out by Andy Beaulieu and shoot down some UFO's over Birdseye images.
John.
So much new Virtual Earth Imagery Worldwide. on Via Virtual Earth Blog
I subscribe to all the VE blogs and recently the posts about updated imagery has been more and more frequent.
The latest is here and for myself downunder we saw three updates, Canberra, Newcastle and Uluru:


Derek Chan posts 3 Articles in a month! on Via Virtual Earth Blog
A big thank you to the efforts of Derek Chan who posted his third VE article today (he actually had it ready weeks ago but had to wait for Mr Bottleneck here at VVE ;) )
The 3 articles are all relivant to Version 5 of Virtual Earth and deal with the Mini Map, debugging javascript and now custom pins in routes.
All these can now be found in our articles section.
If you have something to contribute send us an email.
John (The bottleneck)
How are you getting there? Implementing Driving Directions in Virtual Earth RSS
This article is written for an old version of the Virtual Earth platform. While still available for reference purposes, it is unlikely to work if implemented.
This article starts with the web page created at the end of the Getting Started Part 2 article. In this article we will create a popup context menu to set the start and end points for a journey. We will then discover how to build the code to allow us to retrieve the directions for the journey. Finally we will plot out the route on the map.
This article is also available in PDF format.
Getting the start and end points
In order to get the start and end point of the journey we are going to use a popup menu that will allow the user to set the start and end point and then get the driving directions.
The first step to getting a popup menu to display is to define some styles for how the menu will look. We will do this at the top of the HTML file but in a real world application it would be preferable to use a CSS file.
ul, li
{margin:0;padding:0;}
ul.pmenu
{
position:absolute;
margin: 0;
padding: 1px;
list-style: none;
width: 150px; /* Width of Menu Items */
border: 1px solid #ccc;
background:white;
display:none;
z-index:10;
}
ul.pmenu li
{ position: relative; }
/* Styles for Menu Items */
ul.pmenu li a
{
display: block;
text-decoration: none;
color: black;
padding: 2px 5px 2px 20px;
}
ul.pmenu li a:hover
{
background:#335EA8;
color:white;
}
/* IE \*/
* html ul.pmenu li { float: left; height: 1%; }
* html ul.pmenu li a { height: 1%; }
* html ul.pmenu li ul {left:147px;}
/* End */
In the body section of the HTML code we can now define the menu as:
<ul id="popupmenu" class="pmenu">
<li><a href="#" onclick='setstart()'>Set Start</a></li>
<li><a href="#" onclick='setend()'>Set End</a></li>
<li><a href="#" onclick="getdirections()">Get Directions</a></li>
</ul>
You can see we have define 3 methods that will get called when the menu items get clicked. We will need to implement those.
First let�s implement the code needed to show and hide the menu.
function removepopupmenu(e)
{
var menu = document.getElementById('popupmenu').style.display='none';
}
var popuplat;
var popuplon;
function popupmenu(e)
{
var menu = document.getElementById('popupmenu');
menu.style.display='block'; //Showing the menu
popuplat = e.view.latlong.latitude;
popuplon = e.view.latlong.longitude;
menu.style.left = map.GetX(popuplon)+10; //Positioning the menu
menu.style.top = map.GetY(popuplat)+50;
}
You will notice that the location for the popup menu is being stored in 2 global variables; popuplat and popuplon. We will use these in the setstart and setend methods to place the pushpins on the map.
var startpt;
var endpt;
function setstart()
{
map.RemovePushpin('start');
map.AddPushpin('start',
popuplat,
popuplon,
100,
34,
'pin',
'Start',
1);
startpt = new Msn.VE.LatLong();
startpt.latitude = popuplat;
startpt.longitude = popuplon;
}
function setend()
{
map.RemovePushpin('end');
map.AddPushpin('end',
popuplat,
popuplon,
88,
34,
'pin',
'End',
1);
endpt = new Msn.VE.LatLong();
endpt.latitude = popuplat;
endpt.longitude = popuplon;
}
In order to display the menu we need to attach the popupmenu function to the oncontextmenu event that is raised on the mapcontrol. We can also attach the removepopupmenu function to the onclick event so that the menu is hidden when the user clicks elsewhere on the map.
Attaching the events should happen in the method called by onLoad, in this example it is the OnPageLoad function.
map.AttachEvent("onclick", removepopupmenu);
map.AttachEvent("oncontextmenu", popupmenu);
We now have a popup menu that appears when the user right clicks on the map. This menu allows the user to set a start and end point for the route for which they want directions.
Building the Directions Code
In order to retrieve the directions for the route we will need to build a server side component that can query the directions from the Windows Live Local directions component. This is similar to building the proxy code for the Search or Birds Eye that can be found on in the MSDN documentation.
Microsoft�s directions code is located on the Local.Live.com site: http://local.live.com/directions.ashx.
The directions.ashx page takes 4 parameters; the start latitude, start longitude, end latitude and end longitude. It then returns the JScript code to execute on the local.live.com site. We will need to extract the information from this code to use on our page.
For this example we will build the server side code using C# in ASP.NET 1.1.
Driving directions consist of a set of instructions, each instruction is for a particular location. This can be represented by a simple class in C#:
public class RoutePoint
{
public string instruction;
public decimal lat;
public decimal lon;
}
The first thing we will do in our directions code is create an HttpWebRequest for the local.live.com/directions.ashx page.
private HttpWebRequest CreateDirectionsRequest()
{
HttpWebRequest dirRequest = (HttpWebRequest)WebRequest.Create("http://local.live.com/directions.ashx");
dirRequest.Method = "POST";
dirRequest.ServicePoint.Expect100Continue = false;
dirRequest.ContentType = "application/x-www-form-urlencoded";
return dirRequest;
}
We can then write a method that will place the results from our call to the directions code into a string.
private string GetDirectionResults(HttpWebRequest dirRequest)
{
string results = string.Empty;
HttpWebResponse dirResponse;
dirResponse = (HttpWebResponse)dirRequest.GetResponse();
Stream receiveStream = dirResponse.GetResponseStream();
System.Text.Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(receiveStream, encode);
Char[] read = new Char[256];
// Reads 256 characters at a time.
int count = readStream.Read( read, 0, 256 );
while (count > 0)
{
String str = new String(read, 0, count);
results += str;
count = readStream.Read(read, 0, 256);
}
dirResponse.Close();
return results;
}
We can then use these two methods to call the Microsoft directions code and return the results in a string that we can work with.
private string BuildParams()
{
string dirParams = string.Empty;
dirParams += "&startlat=" + startLat + "&startlon=" + startLon;
dirParams += "&endlat=" + endLat + "&endlon=" + endLon;
return dirParams;
}
private string GetDirections()
{
string results = string.Empty;
string dirParams = BuildParams();
HttpWebRequest dirRequest = CreateDirectionsRequest();
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] bytes = encoding.GetBytes(dirParams);
dirRequest.ContentLength = bytes.Length;
Stream requestStream = dirRequest.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
try
{
results = GetDirectionResults(dirRequest);
}
catch(Exception ex)
{
//not a good idea for production system - log it
Console.Out.WriteLine(ex.Message);
}
return results;
}
Breaking down the route
We can extract the route instructions from the directions string (that contains Jscript specific for Local.live.com) returned from the previous method calls. We are going to do it using a simple string search and replace. (There are probably smarter and more efficient ways to this, but the aim is to explain what we are doing here).
private ArrayList routePoints;
private ArrayList GetRoutePoints(string directions)
{
routePoints = new ArrayList();
// look for new VE_RouteInstruction
string routePtStart = "new VE_RouteInstruction('";
int currentIndex = 0;
do
{
currentIndex = directions.IndexOf(routePtStart, currentIndex);
if (currentIndex!=-1)
{
RoutePoint routePt = new RoutePoint();
int startIndex = currentIndex+routePtStart.Length;
int endIndex = directions.IndexOf("'",startIndex);
routePt.instruction =
directions.Substring(startIndex,
endIndex - startIndex);
startIndex = directions.IndexOf(',', endIndex);
startIndex++;
endIndex = directions.IndexOf(',', startIndex);
routePt.lat = decimal.Parse(directions.Substring(startIndex,
endIndex-startIndex));
startIndex = directions.IndexOf(',', endIndex);
startIndex++;
endIndex = directions.IndexOf(',', startIndex);
routePt.lon = decimal.Parse(directions.Substring(startIndex, endIndex-startIndex));
routePoints.Add(routePt);
currentIndex = endIndex;
}
}
while(currentIndex >0);
return routePoints;
}
We now have the code to create an array list of RoutePoint objects that we can use to plot on the map.
Plotting the route points
We are going to use the same technique that Microsoft uses to display the driving direction on the map. The local.live.com/directions.ashx page returns Jscript that can be executed (using the eval function) on the client side. From the array of RoutePoint objects we are going to build the Jscript to populate the panel and place the points on the map.
private string startLat;
private string startLon;
private string endLat;
private string endLon;
private void Page_Load(object sender, System.EventArgs e)
{
if(Request["startLon"] != null
&& Request["startLat"] != null
&& Request["endLon"] != null
&& Request["endLat"] != null
)
{
Response.Clear();
startLat = Request["startLat"];
startLon = Request["startLon"];
endLat = Request["endLat"];
endLon = Request["endLon"];
string directions = GetDirections();
routePoints = GetRoutePoints(directions);
//first output the jscript to add to the panel
int index = 1;
Response.Write("p.body.innerHTML = \" ");
foreach(RoutePoint routePt in routePoints)
{
string direction = string.Empty;
direction +=
"<a href='javascript:map.SetCenterAndZoom(";
direction += routePt.lat.ToString()
+ "," + routePt.lon.ToString();
direction += ", 18);'>" + index.ToString();
direction += "</a>: "
+ routePt.instruction + "<br/>";
Response.Write(direction);
index++;
}
Response.Write("\";");
//now write out the jscript to add the route points
index = 1;
foreach(RoutePoint routePt in routePoints)
{
Response.Write("map.AddPushpin('" + index.ToString() + "',");
Response.Write(routePt.lat.ToString() + "," + routePt.lon.ToString() );
Response.Write(",30, 34, 'pin', ");
Response.Write(index.ToString() + ",40);");
index++;
}
}
}
The full listing for our directions.aspx code can be found here http://www.viavirtualearth.com/MyVirtualEarth/v2/directions.aspx.cs.txt.
Putting it on the Map
The final step is to call our new directions code and run the code returned (eval) to fill the panel and place the points on the map.
var xmlhttp=false;
function getdirections()
{
if (startpt && endpt)
{
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest!='undefined')
{
xmlhttp = new XMLHttpRequest();
}
xmlhttp.onreadystatechange=directionsHandler;
xmlhttp.open("GET","Directions.aspx?startLat="
+ startpt.latitude
+ "&startLon="
+ startpt.longitude
+ "&endLat="
+ endpt.latitude
+ "&endLon="
+ endpt.longitude
,true);
xmlhttp.send(null);
}
else
{
alert("you need to set a start and end point");
}
removepopupmenu(0);
}
function directionsHandler()
{
if (xmlhttp.readyState==4)
{
ClearPanel();
//remove any existing pushpins
//(could be left from previous directions search)
map.ClearPushpins();
//add the start and end back to the map
map.AddPushpin('start',
startpt.latitude,
startpt.longitude,
100,
34,
'pin',
'Start',
40);
map.AddPushpin('end',
endpt.latitude,
endpt.longitude,
100,
34,
'pin',
'End',
40);
var directions = xmlhttp.responseText;
//use this to examine the returned JScript
//alert(directions);
eval(directions);
}
}
Conclusion
We have now added the ability to get driving directions between 2 locations and plot them on the map. The full sample can be viewed here http://www.viavirtualearth.com/MyVirtualEarth/v2/gettingstartedpt3.htm
One thing that is missing is the ability to plot the path of the route along the roads. This is more complicated than simply drawing lines between the points as roads are generally not that straight. If you require functionality such as plotting the lines you can either delve deeper into the local.live.com directions code or (and I would recommend this) explore a product such as MapPoint Web Service (http://msdn.microsoft.com/MapPoint) that provides this functionality.


