| Ricky's profileRicky's Bing Maps BlogBlogSkyDrive | Help |
|
|
10/4/2009 Point in Polygon and Bounding Box search against data in the Customer Service SiteCurrently when storing data in the customer service site you have the ability to query your point location data by entity id, property, radius search, and find near route. There are two key search functionalities missing. The first is bounding box searching, and the second is point in polygon searches. A bounding box is simple 4 sided regular polygon and as such if we can perform a point in polygon search we can use the same algorithm to perform a bounding box search. This post is going to outline two methods that can be used to perform such a search against data that is stored in the Customer Service Site. Method 1 Lets start off with a polygon (blue). If we find the maximum and minimum latitude and longitude coordinates that this polygon has we can create a bounding box (green) that encloses the polygon. We can then calculate the center point and radius from center point to a corner of this bounding box. Once we know this information we can then enclose this bounding box with a circle (red). The information used to create this circle can be used with the radius search tools that are currently available. If you perform a radius search using the calculated information you will end up with a lot of extra data points. You can filter this data points by running them through a point in polygon algorithm like the one outlined here: http://msdn.microsoft.com/en-us/library/cc451895.aspx. You can then return the filtered data to the user. Using this method your polygon must fit inside a bounding box whose sides are no longer than 353.55 miles. The benefit of this approach is that there are only a few calculations required initially. One down side is that there is a lot of extra data that could be potentially returned. Method 2 The second method is very similar to the first. The maximum and minimum latitude and longitude coordinates of the polygon are used to create a bounding box so that the center of the polygon can be calculated. However, instead of calculating the radius from the center point to a corner of the bounding box, we can loop through and calculate the radii’s from the center point to each point in the polygon. The largest radius can then be used to perform a radius search. Using this approach should reduce the amount of data that is returned by radius search as it is able to enclose the polygon tighter than that previous method. The down side is the number of calculations that need to be performed initially. For complex polygons this can result in slower performance. Using this method you are limited to a maximum radius of 250 miles. Conclusion Using either of these methods will allow you to perform both bounding box and point in polygon searches against your data in the customer service site. Which method should you use. If you are performing bounding box searches or are using complex, predefined polygons then the first method would be ideal. If youare letting the user create the polygon chances are there will only be a limited number of points and as such method 2 would be ideal. I have put together an example that allows you to draw out polygons using the right mouse button (press the left mouse button when done). After you have drawn a polygon you can then use either method to query the FourthCoffeeShops data source. You can down load the sample code here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/CSSFindByPolygon.zip 10/3/2009 Bing Map 3D Altitude Extraction via Mouse ClickWhen I first started with Virtual Earth a few years ago I always wanted to know how to extract the altitude of buildings from the 3D control but unfortunately there wasn’t any documentation on how to create custom plug-ins. There has been numerous people on the forums over the past couple of years who have also been asking for this. I had a good idea of how to go about this but just never got around to doing it, so here it goes. Lets start off with a screen shot of the finished product:
You then need to add a class file to your project called “VE3DMouseAltitudePlugin.cs” and a HTML page called “MouseClickAltitudeFinder.html”. You can now add a strong named key to your project. To create a strongly name key for this plug-in:
Your solution explorer should now look like this: In the VE3DMouseAltitudePlugin.cs file we can add the following references to the top of the file:
If this is done properly the top of your file should look something like this:
To get it to work you may need to re-add the references to the Microsoft.MapPoint dll’s. You will also have to change the path to the project dll in the MouseClickAltitudeFinder.html file. Determining if two bounding boxes overlapOften when displaying polygons you only need or want to show the polygons that are in the viewable area of the map. By doing this an increase in performance should occur with the map control as there will be less data that will need to be handled by the control. One method to go about this is to store the bounding coordinates of your polygon compare then to the bounding box of the viewable map. This leaves you with the task of determining if two bounding boxes overlap which should be much easier than determining if a polygon with any number of sides is in the map view. What this blog is meant to do is to present a mathematical solution to this problem. For this solution we need to break a bounding box into some key components. A bounding box has a center point and two important radii’s. A radius from the center point to and edge in the x direction, and a radius in from the center point to and edge in the y direction. The following diagram illustrates this: By looking at this diagram we can derive two key logical statements about how to determine if two bounding boxes overlap. The first statement is that if the radius from the center of bounding box A to bounding box B We can calculate the x coordinate of the center point by adding the top left x value to the radius on the bounding box in the x direction. We can then determine the distance between centers by taking the absolute value of the different between the x coordinates of the center points of bounding box A and B. This gives use the distance The radius this can then be further reduced to the following: Similarly we can can derive a formula like this for Now we can look at the other side of the equation where we add the radii's of bounding box A and B. Doing this we get the following for the x direction: this can then be reduced to the following: Doing the same for the y direction we get the following: this can then be reduced to the following: We can now take the formula this can then be reduced to the following: Lets call this condition 1. Doing the same for the y direction we get the following: Lets call this condition 2. Now if both condition 1 and condition 2 are true then the bounding boxes A and B must overlap. We can now create a simple function that takes in two VELatLongRectangle objects and returns boolean depending on if the two bounding boxes overlap.
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 8/26/2009 Fix: Bing Maps Mouse Wheel Bug in Firefox 3.5Currently Firefox 3.5 is not supported by Bing Maps although there are only minor issues. One issue is that if your page is scrollable and you use the mouse wheel to zoom in or out of the map the page will also scroll. This is not very good for the user experience. After some investigation I have put together the following workaround to correct this issue:
8/16/2009 Determine if a location has Birdseye ImageryfRecently I was asked how to determine if a specific area on the map has Birdseye imagery. There are several ways to do this using the AJAX control or the Web Service of Bing Maps. However, one of the clients requirements was to be able to determine this before loading a map and without having to create a web service. With this requirement it is not possible to use the built in imagery metadata functionality of the map. There is not supported method to determine if a location has Birdseye imagery without loading a map and without using the Bing Maps Web Services, however it can be done. In the series of blog posts I made called “Birdseye Imagery Extraction via the Virtual Earth Web Services” I described a method to retrieve Birdseye scene information from a background service that is used by the AJAX control. By extending some of the undocumented functionalities of the we can access this backend service through the AJAX control without loading a map. This backend service takes in an array of VEParameter objects. These parameters mush include the latitude, longitude, zoom level, spin direction, and orientation of a Birdseye request. By hard coding the zoom level to 19, the spin direction to “No Spin” and the orientation to “North” we have the highest chance of getting an accurate response as this is the most common Birdseye imagery setting. Once we have created this array we can pass it along with the URL of the backend service, and a callback function into a method called JSONRequestInvoke. In that callback the response contains a property called Scene. If this property is null then Birdseye imagery is not available for the specified location otherwise it does. Below is a basic HTML page that shows how to do this.
8/1/2009 VE Silverlight Control – Pushpins, Infoboxes, and Best Map ViewThe Virtual Earth/Bing Silverlight control CTP release was announced at MIX09. Since this control is still in CTP there are a lot of desired functionalities that have not made it in yet. Currently polygon and polyline shapes are built into the control but pushpins are not. This was by design as it is pretty easy to create your own user control on the map to be used as a pushpin. Not all of the functionalities that are in the AJAX control made have been added to the CTP control. In particular the ability to get the best map view for an array of points, or a common infobox class. This article will show how to create a basic pushpin, create an infobox and how to implement the best map view functionality that I put together here: http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!943.entry Basic Pushpin To create a basic pushpin we will add in the more common properties of the pushpin object that’s in the AJAX control such as, title, description, and LatLong. We will also have properties to specify the pushpin image source, a reference to the map, and an offset that will be used to offset the position of the infobox from the center of the pushpin. to get started we will create our pushpin xaml. A MouseLeftButtonDown event will be added to the pushpin. This event will be used to display the infobox.
For the Pushpin class we will have to create the properties that we want the user to be able to set. The following is used to define the properties of the pushpin class.
The PinClicked methoded that gets fired when a user clicks on a pushpin is used to populate the infobox information. There are several ways for the infobox to be created. To reduce the number of user control instances that are created a single infobox can be used and it’s contents updated depending on which pushpin you clicked on. This will make a significant performance difference when there are a lot of pushpins on the map. The PinClicked method will set the infobox title and discription properties and will make it visible. The infobox Position, PositionMethod, and PositionOffset properties will also be set. The PinClicked method looks like this:
Now that we have our Pushpin UserControl made we can now have to create a method to add these pushpins to the map. In the Page.xaml.cs file we can add the following method to add a pushpin to the map:
For simplicity one icon is used for all pushpins. This can be easily modified so that you can use a different icon for each pushpin. Also, I’ve hard coded in an offset value of 15. This value is used to offset the position of the infobox a certain number of pixels away from the center of the pin. Now that we have a way to add our pushpins to the map the following can be used to add your pushpins:
Note that you will need to add a MapLayer to the Page.xaml file like so:
Infobox control Adding an infobox to the map is similar to adding a pushpin to the map. However, simply displaying an infobox on the map is not enough, ideally we will have logic that will know what direction to display the infobox relative to the pushpin and where it is on the map. The infobox should be displayed towards the middle of the map so that there will be less of a chance of the infobox being displayed off the page. Also, as mentioned above having one infobox and updating it’s properties is will lead to better performance than creating a separate infobox user control for each pushpin. Additionally we will want to add the infobox to a map layer that is above the pushpin layer so that the infobox will be displayed above the pushpins. To get start the following xaml will be added to the map:
This xaml that is used to create the infobox description area is set up so that if the content causes the infobox to grow to it’s max height of 200 pixels a verticle scrollbar appears. The infobox has an close button that calls a method called CloseInfobox when clicked. This method collapses the infobox so that it is no longer displayed. Here is the code for the CloseInfobox method.
We now need to create the tools needed to retrieve the infobox position method, and position offset properties. These properties are dependant on where the pushpin is on the viewable map when the user clicked it. To determine the position method we first want to figure out which quadrant of the map the pushpin is in so that we can display the infobox in the opposite direction. The following methods can be used to determine the position method that should be used:
To calculate the infobox offset we also need to know which quadrant of the map the pushpin falls in so that the offset will be away from that quadrant. The following method can be used to determine the infobox offset:
The pushpin user control will now be able to use these methods to position the infobox on the map. Note that these methods require the map to have a width and height property. Best Map view I have written a couple methods over the years that calculate the best map view for an array of coordinates. The most recent one creates a MapViewSpecification that can be used with the Silverlight control (http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!943.entry). Using this method is pretty straight forward. The following is an example of how to use this method to position the map accordingly:
Conclusion Using the techniques described in this article you should be able to easily create pushpins with infoboxes and also be able to determine the best MapViewSpecification for those pushpins. Source code that uses these methods can be found here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/VESilverlightMap%7C_PushpinsInfobox.zip This sample code also has a MiniMap that Earthware describes how to make in his blog here: http://www.earthware.co.uk/blog/index.php/2009/03/virtual-earth-silverlight-minimap-tutorial/ 7/21/2009 Determining Best Map View for an array of locations
In the past it has been useful to be able to determine the best map view to display an array of locations. In the AJAX control there is a method call SetMapView which determines the best map view for an array of coordinates. The VEWS and Silverlight control do not have this functionality. A long time ago someone wanted to know how to determine the best map view before loading the map. This required us to calculate out the best map view ourselves using map scale information. I later implemented the same method when working with the VEWS so that I could geo-reference images from the Imagery service (http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!488.entry). The method worked fairly well but I knew there was a better way to do this. When working with the Silverlight control I came across a situation where I needed this functionality again so I decided to create the updated method for determining the best map view using similar math that is used for the tiling system. This eliminated the need to maintain a list of scales for each zoom level and also reduce the amount of calculations that needed to be performed. Below is the updated algorithm for determining the best map view for a list of locations:
7/2/2009 Load 3D map control at a specific locationIn the latest release of the 3D map control some new properties were added that allow you to specify where the map should appear when loading. The benefit of this is that the map will load at a specific location where as before you had to load the map and see the whole globe then call the FlyTo method to fly to your location. The properties are called StartAltitude, StartPitch, StartHeading, StartLongitude, and StartLatitude. To set these properties you should use an event handler on the RenderEngine.Initialized event. For example:
Inside the method that gets called by the Initialized event the data sources, and the initial location information can be loaded:
WinForm application that demonstrates how to do this has been uploaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/VE3DFlyToExample%7C_WinForm.zip 6/15/2009 Find Location Nearest to YouCurrently the default behavior of the VEMap.Find function is to center the map over the matching location that is the most popular. This is great most of the time but sometimes it would be nice to be able to search for a location that is closest to where the map currently is. By default the top 10 most popular locations (VEPlace objects) are returned in the find callback. By modifying the properties in the find call up to 20 locations can be return. By setting another property you can prevent the Find method from centering over the most popular match automatically. By calculating the distance from the center of the map to each returned location in the Find callback we can determine the closest (distance) location that matches the users search. The distance from the center of the map to each point can be calculated using the haversine formula: http://rbrundritt.spaces.live.com/default.aspx?_c01_BlogPart=blogentry&_c=BlogPart&handle=cns!E7DBA9A4BFD458C5!317 The following code is an example of how to go about doing this.
5/31/2009 Drawing arrow heads on PolylinesSometimes adding an arrow head to polyline is desired. There are a couple of ways to do this. One way is to use arrow head images as icons and rotate to point in the desired direction. A second method is to extend the polyline and draw the arrow point. The flowing code shows you how to implement the second method.
5/18/2009 Drawing Dashed Routes behind Buildings in Birds eyesRecently I was asked how to draw route lines in Birds eye so that they become dashed when behind a building. Needless to say this turned into a pretty good brain teaser as the dashed lines on the Birds eye tiles are part of the image. So after some thought the possible methods that I could think of included:
I ended up putting together some sample code on how to do the second method. This is were the code for the article "Dashed Polylines in Virtual Earth" originated from. What the code does is defines a set of circular regions where tall buildings are known to exist (user defined) and then calculates the heading of a section of a path (http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!393.entry). If heading is more perpendicular than parallel to the Birds eye orientation the line is drawn as a dashed line. As an added bonus, polylines done appear to be rendered when added in Birds eye mode. So the map needs to be flipped to a different map style, the polyline added, and then flipped back to Birds eye. For simplicity I used an array of points for my route. An actual VE route can be used when using client tokens and retrieving the route geometry (http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!782.entry). The complete source code for this sample can be found here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/dashedRoutes.zip Here is a screen shot of this code in action: Dashed Polylines in Virtual EarthVirtual Earth has a lot of options for for working with shapes, unfortunately there are so many additional options that are not document (thus unsupported) that are available. However, just because it's not documented doesn't mean it can't be used, it just means that it may break at any time and if it does then it's no ones fault but your own. Now that the fair warning is out of the way here is how to draw dashed polylines. Before adding a polyline to the map set the VEShapeStyle.prototype.stroke_dashstyle property to one of the following:
For an added effect, resize the width of the polyline based on the zoom level. I've put together a nice little sample of how to do this which can be downloaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/dashedLines.zip Here is a screen shot of what the sample program looks like: Multiple Routes in Virtual EarthOut of the box Virtual Earth has the ability to draw multipoint routes however it does not have the ability to display more than one route object at a time. Questions on how to do this have been appearing on the Virtual Earth forums for a while now. The general method to do this is to use client tokens with your map so that you can retrieve the route geometry from the Virtual Earth. Once you have the route geometry you can then use polylines to draw any number of routes on your map with out the previous map disappearing. To make things easy I create my own Route object. This object has a polyline which is used to draw the route path, an array of icons to mark the turn by turn points, a directions property which contains HTML that displays the turn by turn directions, a route title which is used to label the route in a list next to the map so that we can display the route markers and directions for a different route, a route color in both Hex and RGB format. RGB format is needed for VE, and hex format is needed for HTML. This object has a prototype called ShowRouteInfo, which hides all pushpins on the map, displays the directions for the route, shows the pushpins icons for the route, and sets the best map view for the route. This object looks like s:
One catch with the routing information that is returned by VE is that if you try and get the custom icon for a leg of the route using the GetcustomIcon method on the VERouteLeg.Shape property you will end up with the default red icon. We can however access the url to the correct icon by referencing the _customIcon property of the VERouteLeg.Shape object. We will also want to create a new pushpin object otherwise our pushpin will not exist after we delete the default route. A simple function to create the correct route icon looks like this:
The rest of the work done in the code base for this is pretty straight forward. The complete source code can be downloaded here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/MultipleVERoutes.zip Here is a screen shot of this code in action: 5/3/2009 Integrating a GPS receiver with Virtual EarthIntegrating a GPS receiver with Virtual Earth has often been a topic that has come up on the Virtual Earth forums. In the book Practical .NET 2.0 Networking Projects there is a great section on how to create a Virtual Earth WinForm application that integrates with a GPS device. The Virtual Earth related code was written for version 3. Virtual Earth is now in its 6th version and the code has changed a lot since version 3. Many others who have attempted to follow the code in the previously mentioned book have had some issues getting the code to work. After hearing a lot of questions on the forums I ended up buying the book myself and put together an updated version of the this application but never got around to posting it online. So its better late than never. I've made a few modifications to the original design. Knowing that I would not always have access to the internet I have set the program up so that even if there is no internet connection it will still be capable of recording the RAW GPS data in a text file. This file can then be read later by the same program when an internet connection is available and display the path on a Virtual Earth map. For the GPS I managed to pick one up used on EBay for $15. It connects to a computer through USB but requires a serial port emulator to work correctly which is available from the GPS manufactures web site. This application requires following steps:
Connecting to a GPS Receiver The first step is to get your computer to recognize your device. Drivers may be needed in order for your device to be made available through one of your serial ports (COM). These drivers usually give you the ability to set which ports your GPS data will be transmitted on and if it will transmit the raw data or NMEA data. You will want to transmit NMEA data. The manufacturer of your GPS Receiver may provide an application to monitor your GPS receiver. This is very useful when debug your application. It also usually allows you to see what other information can be retrieved from the RAW data that the comes from the GPS device. Once your computer is able to connect to your GPS receiver you should be able to connect to it as well. To connect to your GPS receiver from your application we will have a drop down with a list of all the available serial ports so that the user can select the port that their GPS device is connected to. You will want to populate this drop down when the application loads. The following code can be used to retrieve a list of serial ports and fill our drop down with the names:
Our application has a button to connect to the GPS receiver. We will give this button the ability to b oth connect and disconnect to the GPS receiver. If we want to connect to the GPS receiver we will want to close the port if it is already open. Next we can specify the port configuration. Once the port configuration are set the connection can be opened. If we want to disconnect from the GPs receiver we just have to call the Close method of the connected serial port. The following code shows how to do this:
Reading and Processing GPS Data The data that you will be receiving from your GPS will be in NMEA format. NMEA stands for National Marine Electronics Association. The National Marine Electronics Association developed a standard for representing GPS related data, often referred to as NMEA sentences. The following is an example of some NMEA data that I'm able to receive from my GPS: $GPRMC,054715,A,4340.254,N,07923.009,W,0.0,0.0,030509,10.4,W*48 Most GPS devices support the NMEA schema. Here are a list of common NMEA data sentences and their meanings:
More information on NMEA sentences can be found here: http://www.gpsinformation.org/dale/nmea.htm For our application we are only interested in geographical location of where we are. This information is contained in the $GPGGA sentence. The $GPGGA sentence separates it's data using commas. The data in this field has the following meaning:
Note that field 14 and 15 are not comma separated. For our application we will want to latitude, longitude, altitude, and unit of measure of the altitude. We can retrieve this information from columns 2-5, 9,10. To read the GPS data we first need to set up a timer that will consistently query the GPS for data. When the timer fires an event we will call a method called UpdateGPSData.This method will verify that the serial port is open and then will read the current data from the port. It will then verify that data was received. In our application we will output the raw data to a textbox for the user to see. We will then pass the data to method called ProcessNMEAData which will parse the data and update the map if need be. If the user is saving data to a file the data will be written to the file. The UpdateGPSData method looks like this:
The ProcessNMEAData method iterates through each NMEA sentence it receives and passes it on to the appropriate method to be process further. Since we only need the $GPGGA data we will send all data in this sentence to a method called ProcessGPGGA. We will setup the frame work from accessing the other sentences for future use. The ProcessNMEAData looks like this:
The ProcessGPGGA method will parse the raw data in the $GPGGA sentence and will update the appropriate methods. The latitude and longitude values in the NMEA sentence are in degrees, minutes, and decimal minute form. We will want to convert these to decimal degrees. This can be done using the following formula: Note that the vertical bars represent integer division. The direction of the latitude and longitude coordinate can make the respective value negative if the longitude value is in the (W)est direction or if the latitude value is in the (S)outh direction. We will display the current location in a textbox for the user. If the user is connected to the internet then we can send the data to the map to be displayed. If the user is loading in a file of NMEA sentences then this method will call a javascript function called AddPoint. This function creates an array of coordinates. If the user is not loading in a file and has selected the option to follow their position then a pushpin will be used to display the users current location on the map. This is achieved by calling a method called AddPushpin.
Displaying data on a Virtual Earth map A simple HTML page is used to create an Virtual Earth map. This HTML page is loaded into a Web Browser control in our WinForm application. This map will have two shape layers. One to display paths, and one to display pushpins. A function called AddPushpin will remove all other pushpins and create a new pushpin with the data it is sent. A function called drawPath will use a polyline to draw out a path of locations that either the user has currently traveled or have loaded. Four other simple functions are used to add a point to the points array, clear the points array, center the map and update the data. The updateMapData method will send information back to the WinForm application so that it can display the information in a textbox. This HTML page looks like this:
Before we can load the map and display locations on it we need to determine if there is an internet connection. A simple way to do this is to try and make a web request to a well known URL and verify that an "OK" response is received. The following method does this:
In the ProcessGPGGA method we make a call to an AddPushpin method. This method passes our coordinate information to the javascript. This method looks like this:
If the user has decided not to follow their current location on the map but decides they would like to just show the current location on the map this can by centering the map over the current location. The button click event for this functionality looks like this:
Many of the other functionality that are in this application are pretty straight forward and can be found in the source code here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/GPSMapper.zip An idea for integrating some of the data that is in the other NMEA sentences: It should be possible to determine the position of all the satellites that your GPS sees. With this in mind you should be able to create a Virtual Earth 3D application that displays 3D models of the satellites around the globe in the correct position. 4/16/2009 Virtual Earth Image ViewerVirtual Earth is a great tool for viewing geo-spatial information on a map. It offers great user experience by being able to pan and zoom the map. Sometimes you may wish you could do this with a static image of your own. In Silverlight you can use DeepZoom to do this but doing this in a regular HTML web page requires a lot of custom JavaScript. So why not use Virtual Earth to do this for you? There are a couple of ways to do this. One is to us MapCruncher and generate a bunch of tile images and then add them to the map as a tile layer. This often results in a large number of tiles. This will work in both 2D and 3D modes which is great if your viewing geo-spatial imagery but if you only need 2D tools there are other options. Another option is to add the image to the map like a pushpin and to resize it depending on the zoom level. Recently Chris Pendleton blogged about an interesting way to add pushpins to the map by creating image tags and adding them to a div and then adding the div to the map as a shape layer. You can view the post here: http://blogs.msdn.com/virtualearth/archive/2009/04/09/virtual-earth-api-release-information-april-2009.aspx By expanding upon the methods described in this post we can view an image the same way we view a Virtual Earth map. Here is some sample code that demonstrates how to do this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script> <script type="text/javascript"> var map = null; //image dimensions used form scaling var previousZoomLevel = null; //RedrawShapes //View Change Event handler //Event to respond to Birdseye changes //Clear the shapes //Start Zoom event handler //Load Map Event Handler CreateLayer(); //Register for events to update the custom layer function CreateMap() 4/10/2009 Bird's eye RoutesIt was recently brought to my attention that routes are not supported in the Bird's eye map view. Some how this slipped by me as I swear I've seen it working before. After some thought I suspect that this has to do with possible accuracy issues. A few releases ago a new map method was introduced called VEMap.SetShapeAccuracy (http://msdn.microsoft.com/en-us/library/bb877873.aspx). This method only increases the accuracy of pushpin's. Currently if you draw a route and try an view it in the bird's eye map view you will find that there is no route line drawn only segment markers. One way to correct this issue is to retrieve the route geometry (requires a client token) and draw a polyline in place of the route line. Using this method will not increase the accuracy but will allow you to see a route line. In my tests I haven't noticed any real accuracy issues using this method. Complete source code that demonstrates this method can be found here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/BirdseyeRouting.zip Here is a screen shot of a bird's map with a route drawn on it using this method: 4/5/2009 VE 3D Flight Simulator Version 1.1After having such a huge positive response from many people about the Virtual Earth 3D flight simulator I built a couple of weeks ago I decided to make some enhancements to it. The enhancements were mainly focused around improved controls for a XBox controller. I have overridden the default XBox controls that are, by default, similar to the controls for Halo and made them closer to the controls of other common flight simulators. The following controls where overridden: Left thumb control - Y direction: This control used to only move you in a plane parallel to the ground and did not take the pitch of the camera into consideration. This control now allows you to accelerate in the direction the camera is pointing. Left thumb control - X direction: This control used to allow you to strafe to the side. This control now allows you to roll the plane. Right thumb control - Y direction: This control handles the pitch of the plane. Right thumb control - X direction: This control handles turning. Here is a video of the new simulator in action:
Additional enhancement was to hide the default location data that appeared in the bottom right corner of the screen. This was done by adding the following code into the Activate method of the flight simulator plug-in:
The new controls were defined by creating xml that could be added to the built in bindings. There are two ways to get this xml into your plug-in. One method is to create an xml file that needs to be merged with the default bindings xml file that is on the users computer. This requires the dll's of the plug-in to be installed onto the users computer and the dll to be placed in the GAC in order to get the required permissions to access the default bindings file. By using this method you can make it so that your controls are available in all instances of Virtual Earth 3D. An example of this method can be found here: http://blogs.msdn.com/virtualearth3d/archive/2008/05/01/installing-plug-ins.aspx The second method is to store the xml as a string inside of the plug-in and then add the xml data to the bindings. This method is much simpler and reduces a lot of the overhead. An example of this method is used in the following article: http://blogs.msdn.com/virtualearth3d/archive/2008/07/08/animation.aspx This code uses the second method as it reduces the end users work when it comes to playing with the simulator. The new functionality for the left thumb control in the x direction required calculating the LatLong coordinate and altitude of where the plane is suppose to go to. A distance in which to travel is determined based on how much the user pushing the thumb control forward. This distance is then broken into two components, a horizontal and vertical component. These components are determined using the pitch of the camera and some trig. Using the horizontal component and the heading of the camera the destination coordinate of the plane is determined. These calculations are based on the following article: http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!400.entry The camera is then update by extending the CameraControl class. An example of how to do this can be found here: http://blogs.msdn.com/virtualearth3d/archive/2008/10/22/camera-control.aspx Complete source code for this version of the flight simulator can be downloaded here: 3/22/2009 Virtual Earth 3D Flight SimulatorUpdate: Chck out Version 1.1 of this flight simulator here:http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!773.entry The Virtual Earth 3D control is a great tool when you not only want to know where some place is in the world, but also want to know what it looks like. This is particularly useful when traveling to new areas as landmarks can be easily identified ahead of time. Recently Microsoft released documentation on how to develop against this 3D API (http://blogs.msdn.com/virtualearth3d/archive/2009/01/25/documentation.aspx). Infusion development has been working with Virtual Earth 3D for well over a year now developing business applications. Most of these applications have been developed for the Microsoft Surface. Videos of various applications can be found here: http://www.youtube.com/InfusionDevelopment One thing I’ve noticed is that there hasn’t been a lot of development against the 3D API yet outside of the business world. This article is going to show you how to create a simple flight simulator plug-in for Virtual Earth. Here is a screen shot of the finished product to get you motivated to read through this article. You can also download the source code for this here: http://cid-e7dba9a4bfd458c5.skydrive.live.com/self.aspx/VE%20Sample%20code/SimpleFlightSimulator.zip
Note you will need to re-add the references to the Virtual Earth DLL’s. Here is a video to show it in action. Note I was just using the keyboard for the navigation in this screen capture.
Here is a video of it in action using an XBox 360 controller to navigate. The first step is to install the Virtual Earth 3D control if you haven’t done so already. You can download it here: http://maps.live.com/Help/VE3DInstall/ The second step is to create an ASP >NET Web Application project. In Visual Studios 2008 you will have to do the following steps:
The next step is to reference the Virtual Earth 3D DLL’s. 1. From the Solution Explorer, right click the project name and click Add Reference.
4. A reference to System.Drawing, System.IO, System.Runtime.InteropServices, System.Threading and System.Reflection will also be needed.
Now you will have to create the plug-in class. This can be done by doing the following: 1. Right click the new project's name and select Add | New Item.
Part 2 - http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!752.entry Virtual Earth 3D Flight Simulator - part 2Your class should look like this:
There are three methods, Name, Activate and the Deactivate methods, that are a part of the PlugIn class which you will want to override.
You will now create an Airplane class. This class will have three methods, Load, UpdateCockpit, and UpdateGauges. The Load method will create a ScreenImageActor to overlay the airplane cockpit imagery over the map and a ScreenTextActor to create gauge readings. The gauges will display the coordinates of the Airplane (camera), altitude, pitch (horizon) and heading. The UpdateCockpit method will allow you to change the airplane cockpit image. The UpdateGauges method will retrieve all the data required for the gauges and update the ScreenTextActor. The Airplane class should look like this:
Part 1 - http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!756.entry |
|
|