| Ricky's profileRicky's Bing Maps BlogBlogSkyDrive | Help |
|
|
9/13/2009 Panning and Zooming with the Bing Map Imagery Web ServicesThe Bing Maps Imagery service is commonly used for mobile applications. A common issue people have when using the Bing map imagery web services is figure out how to take a map and navigate around it by panning and zooming. Zooming is pretty straight forward as all the user has to do is increase or decrease the zoom level that was used to initially retrieve the map image. Panning on the other hand is much more complicated. Generally when panning you want to move a certain pixel distance from where the user is currently viewing. To calculate the coordinate of a new location knowing our current location, direction (heading) and a distance to travel we can use the method described in this post: http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!400.entry The distance you will want to pan will depend on the size of your map. Generally you will pick a distance in pixels. To use this pixel distance we will have to convert into a physical distance on the earth. To do this we can calculate the resolution of the ground in pixels for a particular zoom level. To calculate the resolution at a particular zoom level and latitude we can use the following formula. This formula came from the following article on the Bing Maps tiling system: http://msdn.microsoft.com/en-us/library/bb259689.aspx The final piece of information that is needed is the direction (heading). Headings generally are an angle in degrees from 0 to 360 with 0 being North, 90 degrees being East, 180 degrees being south and west being 270 degrees. If you want to pan your map North East you will set your heading to 45 degrees. I’ve thrown together a simple application that pulls all this together. Complete source code can be found here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/BingMapsPanZoom.zip 2/22/2009 Drawing Routes with the VE Web ServiceThe Virtual Earth web services are fairly new and as such it does not currently have all the capabilities of it's JavaScript counter part. One key functionality that is not currently available is the ability to draw routes on a map image. This can be done by extending the methods described in the article "VE Imagery Service Polygons and Polylines" found here: http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!497.entry In order to display a route on a map image the following steps will have to be taken: 1) Geocode the start and end points of the route using the Geocoding service. 2) Calculate a Route and have the route geometry returned using the Routing Service. 3) Calculate the best map view for the route path. 4) Request map image from the imagery service that matches the best map view calculated in step 3. 5) Draw the route line on the map image using .NET drawing tools. 6) Draw the route turn points on the map image using .NET drawing tools. Below is an example of a route that was created using the above method. Complete sample code can be found here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/VERouteImageryService.zip 2/14/2009 VEImagery Service Pixel to LatLong calculations
The VEImagery service gives us the ability to render static versions of Virtual Earth Maps. As handy as this is it would also be handy to be able to georeference the image that is returned. The article found here: http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!488.entry explains how to convert from LatLong to Pixel so that custom icons could be added to the map, however the conversion from Pixel to LatLong was not needed at that time. Building on top of the code that was provided in that article the following method can be used to calculate a LatLong value based on the pixel coordinate of a static image. The following formula can be used to perform this calculation.
The complete source code can be downloaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/CustomIconVEService.zip Here is a screen shot of this application in action. 1/7/2009 Birds Eye Imagery Extraction Via the Virtual Earth Web Services - Part 1Using the Imagery service available in the Virtual Earth Web Services, it is possible to retrieve a map image for a specific location (as specified by specific latitude and longitude values). This method however, is not available to the Birds Eye imagery. Rather further functionality must be applied within the Web Services in order to retrieve accurate Birds Eye Imagery Metadata. The information on the Birds Eye scene for the desired location is present in the URI that is used to retrieve the map tiles which make up the Birds Eye scene. To return the tile in which the specified coordinate exits currently a tile id for the map image must first be provided. The extraction of the correct tile id for alternate map styles, using the Quad Key notation is described in the article, Virtual Earth Tile System (http://msdn.microsoft.com/en-us/library/bb259689.aspx). The methodology described in the Virtual Earth Tile System article is unfortunately not applicable to Birds Eye imagery as a standard Birds Eye scene does not fit perfectly into a quad key frame (for example, a Birds Eye scene at zoom level 19 consists of 4 tiles in the x-axis and 6 tiles in the y-axis and at zoom level 20 there are 8 tiles in the x-axis and 12 tiles in the y-axis). Furthermore the Birds Eye scenes do not populate the quad key format properly, rather tiles that are on the edge of a scene, only fill a portion of a standard map tile. This behavior is caused because the Birds Eye images are geo-referenced, high resolution images which are then overlayed onto the Virtual Earth map differently than a standard tile. The following (figure 1), is a Birds Eye scene shown over a standard road view in Virtual Earth at zoom level 19. The red boxes represent the Birds Eye tiles, and the black boxes represent the VE road tiles over the same area. As is evident, the Birds Eye tiles do not properly line up with the edges of the Virtual Earth tiles, which are placed on the map according to the quad key notation. The Birds Eye imagery therefore must be retrieved using a difference methodology than would be used for a standard VE tile.
Figure 1 - Birds Eye over standard map tile at zoom level 19 The Birds Eye geo-referencing information is stored in a database that can only be extracted using the backend web services the Virtual Earth Map Control implements. The data is returned as JavaScript, and can be extracted from the feed using another step, such as regular expressions. With the information retrieved, it is possible to then geo-reference the Birds Eye tiles, or calculate the specific tile id that a coordinate falls into. Note that this is a hack and is completely unsupported as it's possible that a change on VE's side will cause this URL or method to break. The following are the necessary steps to calculate the tile id based on an input coordinate:
1) Retrieve the Birdseye Imagery Metadata for a coordinate using the Virtual Earth Web Services. 2) Retrieve geo-referencing data for the Birdseye scene in which the coordinate resides using backend Virtual Earth web service. 3) Extract geo-reference data from web service response using regular expressions. 4) Convert LatLong to pixel coordinate, relative to top left corner of Birdseye scene. 5) Calculate the x and y tile positions. 6) Calculate tile id from x and y tile positions. 7) Retrieve Birds Eye tile in which the coordinate resides. Retrieve Birds Eye Imagery from Virtual Earth Web Services
Retrieving the Imagery Metadata for a Birds Eye Scene in which a coordinate exists can be accomplished using the following simple example on how to build the request;
The ImageryMetadataResult object contains several properties; the following variables will be needed in either the calculations that follow or in creating the URI to the map tile:
Additional information on how to use the Virtual earth web services can be found in the article, Developing a .NET Application Using Virtual Earth Web Services (http://msdn.microsoft.com/en-us/library/dd221354.aspx). Retrieve Geo-Referencing Data for a Birds Eye scene
Geo-Referencing data for Birds Eye scenes is not available through the Virtual Earth Web Services rather the information needs to be retrieved from a backend web service. The following is an example web service request that can be used to access the service: This request contains multiple variables:
The following is an example of a response from the web service:
Extract Geo-Reference Data from Web Service Response
The web service response contains more information than necessary; the following is the only portion that is needed:
Each variable is defined with a variable name and value in the format: “name”: value. An explanation as to what some variable names means is as follows:
These variables can be extracted using regular expressions similar to the following:
Birds Eye Imagery Extraction Via the Virtual Earth Web Services - Part 2
Convert Latitude & Longitude to Pixel Coordinate
The calculated pixel will be the pixel coordinates relative to the top left corner of the scene. The first step in this calculation is to create a 1x3 matrix of the LatLong coordinate.
Once the LatLong matrix is created a second matrix is needed to store the geo-referencing data XA-XI. This will require a 3x3 matrix.
These matrices need to be multiplied together in the following fashion:
Before the pixel coordinates can be calculated a zoom factor constant is needed.
The following formula’s can then be used to calculate the pixel coordinates:
By expanding out the calculations the pixel coordinates can be calculated as follows:
Calculate X and Y Tile Positions
The X tile position can be calculated by dividing the x pixel location by the width of a tile and rounding this number down to an integer value.
The Y tile position can be calculated by dividing the y pixel location by the height of a tile and rounding this number down to an integer value.
Calculate tile id from x and y tile positions
The X and Y tile positions along with the tileId are calculated for zoom level 19 using the following grid pattern:
Zoom level 20 uses a similar method, however the grid is 8 tiles in the x-axis and 12 tiles in the y-axis. The number of tiles in the x-axis for a particular Birds Eye Scene is stored in the Hcx value and the number of tiles in the y-axis is stored in the Fcy value of the web response to the back end web service. The following formula calculates a tile id from the X and Y tile positions:
Retrieve Birds Eye tile
Here is an example of a URI to a hybrid Birds Eye tile that is provided by the ImageryMetadataResult.ImageUri property: http://{subdomain}.staging.tiles.virtualearth.net/tiles/cmd/ObliqueHybrid?a=03201011031-7384-19-{tileId}&g=213&token={token} There are three properties which have to be set; subdomain, tileId, and token. The subdomain can be assigned any value that is in the ImageUriSubdomains array. The token value should be assigned as a valid client token. The tileId is the id of a specific tile in a Birds Eye scene. Birds Eye Imagery Extraction Via the Virtual Earth Web Services - Part 3
Pixel to Latitude & Longitude
The following calculation show how to convert a Pixel coordinate which is relative to the top left corner of the Birds Eye scene into a LatLong coordinate. The first step in this calculation is to calculate the zoom factor:
Next a 1x3 matrix of the pixel coordinate is created.
Once the pixel matrix is created a second matrix is needed to store the geo-referencing data QA-QI. This will require a 3x3 matrix.
These matrices need to be multiplied together in the following fashion:
The following formula’s can then be used to calculate the pixel coordinates:
By expanding out the calculations the pixel coordinates can be calculated as follows:
Application
A sample application can be downloaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/VEImagery%5E_Birdseye.zip The following is an example of this application in use. The first image is the test coordinate. The second image is the output of the application.
Figure 2 – Birdseye image of a coordinate in Virtual Earth
Figure 3 - Birdseye tile of a coordinate generated using the VE Web Services 11/2/2008 VE Imagery Service, Polygons and PolylinesCurrently the VE Imagery service does not have the ability to render polygons or polylines on a map image. The high level steps involved to accomplish this are as follows: 1) Calculate the best map view for an array of Location objects. 2) Request map image from the imagery service that matches the best map view calculated in step 1. 3) Calculate the pixel coordinate of each location. 4) Use .NET drawing tools to draw polygons and polylines. Many of the steps in this article are explained in the article title VE Imagery Service and Custom Icons The following code block shows how to draw a polygon on a map image from an array of points that form a polygon. private void AddPolygon(BestView view, Image map, Location[] polygon) The following code block shows how to draw a polyline on a map image from an array of points that form a polyline. private void AddPolyline(BestView view, Image map, Location[] polyline) By combining these algorithms with the code in the article; VE Imagery Service and Custom Icons you can add your polygons and polylines to a VE map image. This can be useful to create tile layers when wanting to display a large number of polygons in the JavaScript version of Virtual Earth without having performance issues. Complete source code can be downloaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/VEPolygonsImageryService.zip 10/25/2008 VE Imagery Service and Custom IconsCurrently the VE Imagery service has the ability to display 26 different icons on the map. Oddly enough the default pushpin icon from the JavaScript version of Virtual Earth is not one of these icons. Unfortunately there is currently no built in method to display custom icons on the map image. There is also currently a limitation of 10 pushpins being passed to the imagery service. This article shows how to add any number of custom icons to the map image in the correct location. The default pushpin icon from the JavaScript version of Virtual Earth will be used as the custom icon. The high level steps involved to accomplish this are as follows:
Calculate the Best Map ViewThe best map view is the zoom level and center point of a map image that contains all locations with the closest zoom level. The best map view will be stored using a structure. /// <summary> /// Structure to define a BestView object which defines a map view (centerpoint and zoom level) /// </summary> struct BestView Listing 1Structure to define a BestView object The following method calculates the best map view for an array of locations. This results in a map image similar to what is displayed if the VEMap.SetMapView function is used in the JavaScript version of Virtual Earth. /// <summary> /// Calculates best map view for an array of points. Similar to VEMap.SetMapView method /// </summary> /// <param name="points">Array of Location objects</param> /// <returns></returns> private BestView CalculateMapView(Location[] points) Listing 2 Method to calculate the best map view for an array of Locations The method that calculates the best map view uses a method called HaversineDistance. This method calculates the distance in kilometers between two coordinates using the Haversine formula. The code for this method is as follows: /// <summary> /// Calculate the distance in kilometers between two coordinates /// </summary> /// <param name="lat1"></param> /// <param name="lon1"></param> /// <param name="lat2"></param> /// <param name="lon2"></param> /// <returns></returns> private double HaversineDistance(double lat1, double lon1, double lat2, double lon2) Listing 3 Haversine distance method Request Map Image from the Imagery ServiceBy specifying a specific zoom level and center point for a map, this ensures that we have at least one point of reference between pixel coordinates and a latitude/longitude coordinate. The following method retrieves an image URL of a map for a specific map view. The image is then retrieves using a stream. /// <summary> /// Gets map from VE Imagery Web Service /// </summary> /// <param name="view">Map view</param> /// <returns></returns> private Image GetMapImage(BestView view) Listing 4 Method to retrieve map image from the VE Web Services for best map view Calculate Pixel Coordinate for a LocationVirtual Earth tiles are positioned using quad key tile positioning. In Virtual Earth a map tile is 256 pixels by 256 pixels. For zoom level one, there are 4 map tiles displayed, making the total map width and height to display the whole world 512 pixels by 512 pixels. If the zoom level is 2, there are 16 map tiles being displayed, making the total map width and height to display the whole world 1024 pixels by 1024 pixels. Additional information the Virtual Earth tiling system can be found here: http://msdn.microsoft.com/en-us/library/bb259689.aspx With the Virtual Earth tiling system in mind, all pixel coordinates for a set of latitude/longitude coordinates can be calculated. Using the center point of the map image the top left hand corner of the map image that is returned by the Virtual Earth imagery service can be calculated as a pixel location on a map that displays the whole world. Relative pixel coordinates can be then calculated for all location latitude/longitude coordinates. The following method takes in a Location object and a BestView object and returns a Point object which refers to the pixel location of a latitude/longitude coordinate on the map image. /// <summary> /// Converts a latlitude longitude coordinate to a pixel coordinate of a map based on the map view /// </summary> /// <param name="latlong"></param> /// <param name="view"></param> /// <returns></returns> private Point LatLongToPixel(Location latlong, BestView view) Listing 5 LatLong to Pixel coordinate method Putting it all together In order for these methods to work in a WinForm application the following references will have to be made: using System.Drawing.Design; Listing 6 Required References A reference to the Virtual Earth Imagery Service and the Virtual Earth token service will also be required. The following global variables will also be needed: string clientToken; Listing 7 Global Variables The following method will calculate the best map view for an array of locations, retrieve a map image from the imagery service, add custom icons to the map image and then display the map image in a picture box. /// <summary> /// Generate map image with custom icons /// </summary> /// <param name="points">Array of Location objects</param> private void GenerateImage(Location[] points) Listing 8 Method to Generate map image with custom icons The following method can be used to add the custom icons to a map image: /// <summary> /// Adds custom icon image to map image /// </summary> /// <param name="view"></param> /// <param name="map"></param> /// <param name="points"></param> private void AddCustomIcon(BestView view, Image map, Location[] points) Listing 9 Method to add custom icons to a map image This method can add a custom icon image and specify an image offset similar to the VECustomIconSpecification. Here is an example of five locations plotted onto a map using Virtual Earth: Figure 2 Points plotted using the JavaScript version of Virtual Earth Here is an example of the same points being plotted onto a map image that is generated from the Virtual Earth Imagery Service using the methods in this article. Figure 3 Custom icons on a VE Imagery Service image ConclusionCombine these methods with a valid client token and you will be able to add your custom icons to a map image. Complete sample code can be found here: This article was written by Richard Brundritt. Richard works for Infusion Development. |
|
|