Today we released updates to the Microsoft Virtual Earth AJAX control and a new version of the Virtual Earth 3D map control. We’ve added a couple new methods for adding and removing pins (and DIVs) in the AJAX control; added performance improvements for AJAX and 3D; enhanced geocoding and parsing across the board (AJAX and Virtual Earth Web Service) and fixed a few bugs in the AJAX and 3D controls. There are lots of architectural changes behind the scenes that you won’t appreciate unless you’re inside Microsoft, so I will spare you the details of those. Now, that being said, for the AJAX map control we just upgraded Version 6.2, so you already have access to the new features and can start using them today without changing your link to Virtual Earth. Everyone is on 6.2 because we’ve either auto-upgraded you or you made the switch yourself. The Virtual Earth 3D control will require an update! Download the latest bits by going to your favorite Virtual Earth-powered web site (such as Live Search Maps) and click 3D and you will be prompted to install the latest bits.
Here’s a little breakdown of the new features for your reading pleasure:
Native Support for Internet Explorer 8 – with the release of Internet Explorer 8, you can now expect the Virtual Earth AJAX map control to function as expected. Download the latest version of Internet Explorer (8).
New Virtual Earth AJAX Map Control Methods – 2 new methods for advanced users to speed up performance and give control over rendering HTML elements on the map.
- AddCustomLayer() – AddCustomLayer allows you to add pushpins to a DIV and then add the DIV to the map control. There are some significant performance improvements for doing it this way. See sample code at the end of the blog post.
- RemoveCustomLayer() – RemoveCustomLayer() allows you to delete the DIV and all it’s elements that were added as a part of AddCustomLayer(). See sample code at the end of the blog post.
Geocoding and Parsing Improvements – our international users will be ecstatic with the geocoding and parsing engine improvements in addition to our new spatial geocoder which helps with accuracy of place name matches for locality queries. The countries / areas where improvements will be noticeable include United Kingdom, Germany, and Spain.
Extended Local Listings – in addition to our current United States local listings available in the Virtual Earth AJAX map control and Virtual Earth Web Service, we’ve extended the indices available in the map control to include listings from France, Italy and Germany.
New 3D Control – an upgrade of the Virtual Earth 3D control will be required to get access to the performance benefits and new features associated with the new 3D control. The performance benefits include compression of building textures for all 1.4 million buildings in the Virtual Earth 3D control (yes, 1.4 million). There are no changes or deletions for the public API for the following assemblies: Microsoft.MapPoint.Data.dll, Microsoft.MapPoint.Geometry.dll, Microsoft.MapPoint.Rendering3D.dll, Microsoft.MapPoint.Rendering3D.Utility.dll, Microsoft.MapPoint.UtilityPartialTrust.dll - redirects are included within so as not to break any applications that may be leveraging them. As always, expect some code samples from the Virtual Earth 3D Team’s Blog. As for new features, here’s an exhaustive list:
- Anisotropic Filtering – This will greatly reduce blur and preserve detail at the 3D control’s extreme viewing angles. This is now an option in the 3D preferences on Live Search Maps (go to Live Search Maps, click options, click 3D Settings, check the box for “use anisotropic filtering").
- Initialized event - A single event on RenderEngine that simplifies the startup scenario.
- Digital Elevation Model data - The ability to supply custom DEM data, and have it automatically stitched into existing data.
- ILocationListener - An interface that allows automatic and efficient query of a location to determine elevation as data changes.
- Synchronous rendering - Manual render functions that allow use of a custom render thread, good for offline rendering or incorporation into another product.
- Datasource ConnectionParameters - Helper function for specifying data sources without a content manifest.
- CelestialStyle - Allow display of a stylized sky with constellations (used in Road Mode on Live Search Maps).
- Versioning - Support for running code built against previous control versions, if it meets certain requirements.
- Pixel-width lines - GeometryManager supports pixel-width 3D lines (previously only single-pixel or meter-width). Also nice looking text labels.
- Constant value datasources - Helper functions for supplying flat color or elevation data.
- Terrain Scaling - This works now.
- Override OnPaint - Can replace the loading screen.
- Building Culling Value - Allows control of how many buildings are displayed, based on distance and size of the buildings.
- Turn on/off street level navigation - Can turn off some of the special effects that occur when right next to the ground.
Updated Software Developer Kit – the Virtual Earth AJAX map control SDK on MSDN has been updated to reflect all of these changes.
Sample Code for New Virtual Earth AJAX Map Control Methods – the following sample illustrates the speed of rendering 500 pushpins on the AJAX map control using the new AddCustomLayer() method and provides the render time in milliseconds. There’s also a button for removing the DIV from the AJAX map control using the RemoveCustomLayer() method.
<!---Begin Sample Code for AddCustomLayer() and RemoveCustomLayer() -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title>Virtual Earth v6 API - Custom Layer Sample</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
var map = null;
var myLayer = null;
var numShapes = 500;
//var numShapes = 1;
var pinImage = 'http://dev.virtualearth.net/mapcontrol/v6.2/i/bin/6.2.2008082210001.41/pins/poi_usergenerated.gif';
var pinXOffset = -25 / 2; //width of pushpin image divided by 2
var pinYOffset = -30; //height of pushpin image since we want bottom point of image to point to LatLong
var mapSurface = null;
var previousZoomLevel = null;
var ll = new Array();
//Generate 500 random latlongs 20 degrees around the center
ll = new Array();
var i = 0;
var center = map.GetCenter();
for (; i < numShapes; ++i)
ll.push(new VELatLong(center.Latitude + Math.random() * 20 - 10, center.Longitude + Math.random() * 20 - 10));
//ll.push(new VELatLong(47.6205198, -122.349280));
var s = new Array();
var i = 0;
for (; i < numShapes; ++i)
pixel = map.LatLongToPixel(ll[i]);
s.push("<img src='" + pinImage + "' style='position:absolute; left:" + (pixel.x + pinXOffset) + "px; top:" + (pixel.y + pinYOffset) + "px;' +/>");
myLayer.innerHTML = s.join('');
var timeOutput = document.getElementById('TimeOutput');
timeOutput.innerHTML = '';
if (myLayer == null)
//Clear any existing shapes
//Generate the Random LatLongs
var startTime = new Date();
//Draw the shapes
var totalTime = new Date() - startTime;
timeOutput.innerHTML = totalTime + " ms";
//View Change Event handler
//if zoom level changed, then redraw the shapes, otherwise do nothing -- the map will position the pins on pan properly
var currentZoomLevel = map.GetZoomLevel();
if (previousZoomLevel != currentZoomLevel)
previousZoomLevel = currentZoomLevel;
//Event to respond to Birdseye changes
//When Birdseye rotation changes, redraw the shapes
//Clear the shapes
myLayer.innerHTML = '';
//Start Zoom event handler
//When zoom is staretd clear the shapes before zoom since they will need to be redrawn
//Load Map Event Handler
//Store previous zoom level as current zoom level
previousZoomLevel = map.GetZoomLevel();
//Register for events to update the custom layer
//Create the custom layer for the map dynamically on the map surface
myLayer = document.createElement('div');
myLayer.style.position = "absolute";
myLayer.style.top = "0px";
myLayer.style.left = "0px";
myLayer.style.width = "600px";
myLayer.style.height = "400px";
myLayer.style.zIndex = 1000;
map = new VEMap('myMap');
map.onLoadMap = EventMapLoaded;
myLayer = null;
<div id='myMap' style="position:relative; width:600px; height:400px;"></div>
Click on "Add Shapes" to add 500 random shapes to the map."
<input type="button" value="Add Custom Layer" onclick="AddClicked();"/>
<input type="button" value="Remove Layer" onclick="RemoveClicked();"/>
Time: <span id="TimeOutput"></span>
<!--- End Sample Code for AddCustomLayer() and RemoveCustomLayer() -->
Although, not as feature rich as some previous releases you can see a shifted focus on performance. Enjoy.