Section 2.2. Programming with MapPoint 2004 API


2.2. Programming with MapPoint 2004 API

The MapPoint 2004 APIs were originally designed for use with the COM programming model. In order to build applications using the Microsoft .NET Framework, you need the interoperable assemblies for the MapPoint COM library. Let's look at how to add the MapPoint 2004 APIs as references for use in your project.

2.2.1. Adding MapPoint 2004 References Using Visual Studio .NET

If you are using Visual Studio .NET Version 2003 or later, it is easy to add a reference to the MapPoint 2004 APIs using the Add Reference option from the project context menu, as shown in Figure 2-2.

Figure 2-2. Project Add Reference menu


If you are using MapPoint ActiveX Control, you don't need to add this reference manually, since Visual Studio .NET adds it automatically when you drag-and-drop the control on your Windows Form.


When you see the Add Reference dialog window, select the COM tab and select the Microsoft MapPoint 11.0 Object Library (North America) to add the MapPoint 2004 type library as a reference to your project, as shown in Figure 2-3.

Figure 2-3. Adding the MapPoint 2004 library as a reference


If you are using the MapPoint 2004 European Edition, select the Microsoft MapPoint 11.0 Object Library (Europe) to add the reference. Also, note that if you have both MapPoint North America and MapPoint Europe installed on the same computer, you can develop an interop assembly for either product for use with both applications.


In this process, Visual Studio .NET automatically creates an interoperable assembly and adds it as a reference to your project. By default, the namespace of the newly created assembly is set to MapPoint.

2.2.2. Adding MapPoint 2004 References Using TlbImp.EXE

If you do not have Visual Studio .NET, or if you chose to do the hard work of creating the interoperable assembly yourself, you can use the TlbImp.EXE tool (located in the Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin directory) that ships with the .NET framework. For example, to generate the interoperable assembly for MapPoint 2004 type library with the namespace Interop.MapPoint, use the following command-line command:

     C:\>tlbimp.exe "C:\Program Files\Microsoft MapPoint     \MPNA82.tlb" /out:"C:\Interop.MapPoint.dll" /namespace:Interop.MapPoint /sysarray/     transform:dispret 

This command generates the interoperable assembly Interop.MapPoint.dll in the C:\ directory; add it to your project as a reference as you would do with any other .NET assembly.

Now that you have added the MapPoint 2004 object library to your project as a reference, let's get started with a simple application.

2.2.3. Finding a Place

When you think of mapping in general, the first thing that comes to mind is finding a locationwhether it is a place or an address. A place is a general location referred by its commonly known name; an address is a more detailed specification of a location. For example, one of the best-known places in Seattle is the Space Needle, but the actual address of the Space Needle is 498 Broad St, Seattle, WA 98109. Using MapPoint 2004, you can find both places and addresses, as well as other elements that I discuss later.

Let's start off by building a simple Windows application that finds a place and returns the address for that place. This application contains a text box to input a place name and a button that can be used to fire an event to find the input place. When the input place is found, the address of the place is displayed in the text box labeled Address. The Windows form layout, which you can lay out in Visual Studio, is shown in Figure 2-4.

Figure 2-4. Find Place sample application


Because the user interface code is highly repetitive and generated by Visual Studio, I won't list it here. It is included in the sample files in the download.


Now, let's write the code that is invoked when the Find button is clicked. The root of MapPoint 2004 API programming is the ApplicationClass, so let's start by creating an instance of ApplicationClass:

     //Create an instance of ApplicationClass     //Important Note: You need to clean up after you are done with the     //application class. For more informantion, see the section     //"Cleaning Up After You're Done"     MapPoint.ApplicationClass app = new MapPoint.ApplicationClass( );

After creating the ApplicationClass, access the Map instance via the ActiveMap property:

     //Get a reference to the Map instance via the ActiveMap property      MapPoint.Map map = app.ActiveMap;

The MapClass exposes a method, FindPlaceResults, that returns all places matching the input query. This method takes the place name string as input and returns FindResults, which is a collection of locations found. The following code shows the FindPlaceResults method call:

     //Call FindPlaceResults on the MapClass instance     MapPoint.FindResults findResults = map.FindPlaceResults(this.textBox1.Text);

When the method call is complete, the FindResults instance will contain all the locations that matched the input query. The number of matches is represented by the Count property of the FindResults instance. In our example, the search for "Space Needle" resulted in 25 matches. Next, we need to go through the list to figure out which instance represents the Space Needle in Seattle. So, let's add a modal dialog to show a ListBox control with all found locations so that we can disambiguate the results manually.

Each location that matched the input place is represented as an instance of MapPoint.Location class in the FindResults object. Even though the FindResults class is essentially a collection of Location objects, its behavior is quite different from any .NET collectionyou cannot directly access the Location items in the FindResults collection using the index number:

     FindResults.Items[index]

In fact, the Items indexer is not exposed in the FindResults class in the interoperable assembly; however, there are still two ways to get the Location objects from the FindResults collection, using either the get accessor method or an enumerator.

2.2.3.1. Using the get accessor method

Collections are implemented using two special accessor methods called get_Item and set_Item. For read-only properties, only the get_Item method is implemented. These special methods are generated by the .NET compiler for every publicly exposed property. In case of FindResults instance, even though the read-only Items property is not exposed in the interoperable assembly, the get_Item method is still implemented internally. The only differences from the conventional .NET get_Item method are that this method takes the index value as an object passed by reference (for COM marshalling purposes) and the index starts from 1 instead of 0.

The following code shows how to use the get_Item accessor method to iterate through the list of Location objects in the FindResults collection:

     //Create an object to hold index value     object index = null;     //Start with index 1 instead of 0     for(int i=1; i<=findResults.Count; i++)     {         //Box the integer value as an object         index = i;         //Pass the index as a reference to the get_Item accessor method         MapPoint.Location loc = findResults.get_Item(ref index) as MapPoint.     Location;         if(loc != null)             this.listBox1.Items.Add(loc.Name);     }

2.2.3.2. Using an enumerator

You can also access the list of Locations from FindResults instance using the enumeration. The FindResults instance exposes a method, GetEnumerator, to get an enumerated list of locations. Using this enumerator instance, you can loop through the list of locations as follows:

     //Get an enumerator using the GetEnumerator method      IEnumerator locationEnumerator = findResults.GetEnumerator( );     //Loop through the location instances to get the names     while(locationEnumerator.MoveNext( ))     {         MapPoint.Location loc = locationEnumerator.Current as MapPoint.Location;         if(loc != null)             this.listBox1.Items.Add(loc.Name);     }

The net effect is same for both methods, but the code in the enumerator approach looks cleaner than the get_Item accessor approach. However, the get_Item accessor approach performs better than the enumerator approach, especially when a large number of locations is found. The get_Item accessor method also provides a way to access the desired item directly instead of looping through the entire list.

We can use either method to populate the list of locations in the ListBox of the modal dialog, as shown in Figure 2-5.

Figure 2-5. Disambiguation modal dialog


Look at the list to get the address. From the list of 25 found locations' names from our query, the first name reads "Space Needle [tower], Seattle, WA," which is what we are looking for. Since this is the very first instance in the list, you can use the index to obtain the Location object and the StreetAddress property to get the actual address:

     object currentLocationIndex = findResModalDlg.SelectedIndex + 1;     MapPoint.Location loc = this.findResults.get_Item(ref index) as MapPoint.Location;     //Access the StreetAddress property   for address     if(loc != null)     {         if(loc.StreetAddress != null)             this.textBox2.Text = loc.StreetAddress.Value;         else             this.textBox2.Text = loc.Name;     }

There are a couple of things of note in this code:

  • We are adding 1 to the selected index because the items in the ListBox are zero-index based, but the locations in FindResults collection start with index 1, so to offset this difference, you need to add 1 to the selected index manually.

  • Not all locations have addresses. Although it sounds strange, what address would be returned if you searched for "Seattle" and the returned location was "Seattle, WA"? In cases like this, it is sufficient to return the name of the location.

After obtaining the desired Location object from the FindResults collection, you can access the street address from the Location.StreetAddress property. We now have the address for the Space Needle, which is "498 Broad St, Seattle, WA 98109."

You may be wondering why MapPoint 2004 can't tell you whether there is a best location match instead of making you go through the list to disambiguate the locations each and every time. Actually, it does tell you.

2.2.3.3. Programmatically disambiguating the results

The locations in FindResults collection are always ordered in the best match order, so the first location is always the best possible match according to MapPoint 2004. However, the results depend on the input received by the program; for example, if you misspell the name "Space Needle" as "Spac Neele," MapPoint 2004 won't necessarily display the best possible match first; it is up to you to disambiguate the results using the given list of locations. How do you know as a programmer that MapPoint 2004 has made the best possible match in the FindResults collection? It's actually very simple. Using the ResultsQuality property of the FindResults collection, you can tell whether MapPoint 2004 succeeded in finding the exact match to the input location or whether it is offering a list of possible matches and expecting you to disambiguate. The ResultsQuality property is of GeoFindResultsQuality type, which is an enumeration with the values shown in Table 2-2.

Table 2-2. Values for the GeoFindResultsQuality enumeration

ResultsQuality value

Meaning

Need to disambiguate?

geoAllResultsValid

All location matches are exact matches to the input query.

Not applicable. This value is not returned for finding places or addresses; instead, it is returned for finding points of interests (discussed later in the chapter).

geoFirstResultGood

The first location is an exact match for the input query.

No. You can safely return the first location from the FindResults instance.

geoAmbiguousResults

At least the first two locations are good matches.

Yes. You can safely return the first location from the FindResults instance.

However, since at least the first two results are best possible matches, sometimes you may have to disambiguate between the two.

geoNoGoodResult

There are some location results, but none of them is really a good match according to MapPoint 2004.

Yes. In this case, you don't know what the input query intended to find, so you have to disambiguate the location results.

geoNoResults

No locations found at all.

Not applicable.


Now, with this background, let's extend our sample application to disambiguate the location results programmatically:

     //See if the FindResults.ResultsQuality is either     //geoFirstResultGood or geoAmbiguousResults     if(findResults.ResultsQuality ==                MapPoint.GeoFindResultsQuality.geoFirstResultGood        || findResults.ResultsQuality ==                MapPoint.GeoFindResultsQuality.geoAmbiguousResults)     {         //No need to disambiguate, just return the street address         //of the first location         currentLocationIndex = 1;         //Get the Location object         MapPoint.Location loc             = this.findResults.get_Item(ref currentLocationIndex) as MapPoint.Location;         //Access the StreetAddress property for address         if(loc != null)         {            if(loc.StreetAddress != null)              this.textBox2.Text = loc.StreetAddress.Value;            else              this.textBox2.Text = loc.Name;         }     }     else     {       //Add disambiguation process and show modal dialog       FindResultListDlg findResModalDlg = new FindResultListDlg(ref findResults);       if(findResModalDlg.ShowDialog( ) == DialogResult.OK)       {         //Process the selected location from the find results list         . . .       }     }

Adding this code gets the street address of the input query "Space Needle" without requiring any manual disambiguation.

Now, does this application work if you enter an address as input? A quick test with the address "498 Broad St, Seattle, WA, 98109" shows that this application does not work with addresses because the FindPlaceResults method that we are using treats every input location as a place, so to find addresses you need to use the FindAddressResults method.

2.2.4. Finding an Address

MapPoint 2004 API provides a way to find addresses. The Map class has a method, FindAddressResults, which you can use to find addresses. Unlike the FindPlaceResults method, this method takes a full or partial address to find the intended location. So, in order to use the FindAddressResults method, you have to provide at least one of the following parts of an address:

  • Street address

  • City

  • Other city (used for UK addresses)

  • Region (or state/province)

  • Postal code (or Zip Code)

  • Country

The Country parameter is expressed as a GeoCountry enumeration, while the rest of the parameters are strings. For example, if you want to find the address "498 Broad St, Seattle, WA 98109" in the United States, you have to use the GeoCountry.geoCountryUnitedStates value for Country. The following code shows how to invoke the FindAddressResults method on a Map class:

     //Create an instance of the MapPoint application class     MapPoint.ApplicationClass app = new MapPoint.ApplicationClass( );     //Get the Map object from the application object     MapPoint.Map map = app.ActiveMap;     //Call the FindAddressResults method      MapPoint.FindResults findResults = map.FindAddressResults(                                             "498 Broad St",                                             "Seattle",                                             string.Empty,                                             "WA",                                             "98109",                                 MapPoint.GeoCountry.geoCountryUnitedStates);

Note that when a Country parameter is supplied, the address provided must match that country's address format, or the FindAddressResults method throws an exception. For example, if you pass the above address for GeoCountry.geoCountryUnitedKingdom (UK), the FindAddressResults method throws an exception (since some UK addresses expect the Other City parameter).

For a full list of the GeoCountry enumeration values, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mappoint2004/BIZOMMFindAddressResults.asp.


The quality of the locations returned by the method can be determined by the ResultsQuality property of the FindResults object. The rules that we have discussed in the previous section to disambiguate the locations results are applicable to this method as well.

Do you always need to have the address in the previously described format? Our application collects the input location into a simple textbox as a string, so is it possible to have an address entered as a single string so that you can programmatically parse the address before calling the FindAddressResults method? Absolutely; MapPoint 2004 has a method to do this.

2.2.4.1. Parsing a string into valid street address

The Map class has a method, ParseStreetAddress, that parses a string into a valid street address represented as the StreetAddress class. The StreetAddress class has the Street, City, OtherCity, PostalCode, Region, and Country properties that represent various parts of an address. The Value property of the StreetAddress class gives the full address as one string. The following code shows how to parse a string into a valid address:

     //Create an instance of the MapPoint application class     MapPoint.ApplicationClass app = new MapPoint.ApplicationClass( );     //Get the Map object from the application object     MapPoint.Map map = app.ActiveMap;     //Parse the address     MapPoint.StreetAddress address =         map.ParseStreetAddress("498 Broad St, Seattle, WA, 98109");     //Now get the values from the     //StreetAddress properties     string streetName = address.Street;     string city = address.City;

If you are using this method with MapPoint 2004 European Edition, it is a good idea to include the country information in the address string to ensure accurate results.


So, which method is right for your application? Is it FindPlaceResults or FindAddressResults (along with ParseStreetAddress method)? The answer depends on the requirements of your application. If you expect users to type a well-formatted address all the time, then it is safe to use the FindAddressResults method. On the other hand, if you have an application that expects only place names as input locations, then you should use the FindPlaceResults method. However, if you have an application that can accept both place names and well-formatted addresses, which method do you use, FindPlaceResults or FindAddressResults? Neitheruse the FindResults method instead.

2.2.5. Finding Both Places and Addresses

The Map class has a method, FindResults, that can find both places and addresses. This method takes the input location as a string and tries to parse the string into a valid address. If the input string is successfully parsed into an address, then a FindAddressResults method is called to find the input location; when the input string cannot be parsed into a valid address, the FindPlaceResults method is called. The following code snippet shows how to use the FindPlaceResults method:

     //Create an instance of the MapPoint application class     MapPoint.ApplicationClass app = new MapPoint.ApplicationClass( );     //Get the Map object from the application object     MapPoint.Map map = app.ActiveMap;     //Works with finding addresses     MapPoint.FindResults findAddressResults         =  map.FindResults("498 Broad St, Seattle, WA, 98109");     //Works with finding places     MapPoint.FindResults findPlaceResults         =  map.FindResults("Space Needle");

Let's replace the FindPlaceResults method in our application with the FindResults method call to support both place names and addresses:

     //Call FindResults on the MapClass instance to support both places and     //addresses     MapPoint.FindResults findResults = map.FindResults(textBox1.Text);

You know that our application works for both places and addresses and also handles location disambiguation well, but you may be wondering whether you need to create a user interface (UI) to support each method, since each find method's input formats are so different. You actually don't need tofor applications like ours, there is a method exposed by the Map class that uses the pre-built MapPoint UI.

2.2.6. One UI Finds All

The Map class exposes the ShowFindDialog method to show the built-in find dialog, a modal dialog that implements the FindResults and GetLocation methods along with a nice disambiguation process with a great UI. This method returns either a Location or a Pushpin class instance. Don't worry about the details of the Pushpin class yet; I will discuss this class in detail in the next chapter. For now, consider the Pushpin class to be a graphical mark or shape that represents a location. You can access the Location represented by a Pushpin using the Pushpin.Location property.

The ShowFindDialog method takes the input location as a string. The other parameters include:


FindState

This parameter is of GeoFindState type, which is an enumeration. Use GeoFindState.geoFindDefault if you don't know what type of find (place or address versus latitude and longitude) you may be performing. If you know a specific find that you want to show as the default, set the enumeration value to be geoFindAddress or geoFindPlace.


HWndParent

This is an integer that represents the parent window handle of the find modal dialog. Set this parameter's value to 0 if there is an active, visible MapPoint 2004 application window; if not, pass the current window's handle as an argument.


AutoConfirmExactMatch

This is a boolean that tells the find dialog to hide when an exact match to the input location is found. The default value is false.

The following code shows the implementation of this method for our application:

     //Get a reference to the Map instance via the ActiveMap property     MapPoint.Map map = app.ActiveMap;     //Call the ShowFindDialog to show the find (modal) dialog     object result = map.ShowFindDialog(                               this.textBox1.Text,                               MapPoint.GeoFindState.geoFindDefault,                               (int) this.Handle,                               false);     //See whether the result is null     if(result != null)     {         //If the result is a Location type get the         //Location directly         if(result is MapPoint.Location)         {             currentLocation = result as MapPoint.Location;         }         else if(result is MapPoint.Pushpin)         {             //If this is a Pushpin type, first get the Pushpin             MapPoint.Pushpin pushpin = result as MapPoint.Pushpin;             //Then get the location             currentLocation = pushpin.Location;         }     }     else     {         MessageBox.Show("No locations found. Please verify the input.");     }

You need to check for the return type after the ShowFindDialog method returns a value. If it is a Pushpin type, access the corresponding Location object via the Pushpin.Location property.

Figure 2-6 shows the MapPoint find dialog shown for the "Space Needle" search.

We know our application works for place names and well-formatted addresses. Since we also know exactly where the Space Needle is, let's extend our application to do a bit more and find points of interest around the Space Needle.

2.2.7. Finding Points of Interest Around a Location

Points of Interest (POI) are places that may be of some interest; for example, to a tourist in Seattle, the POI could be the Space Needle, among other interesting things to see; for a coffee connoisseur in Seattle, the POI could be a list of coffee shops. If we take the interest out of context, the POI are simply locations. Each location has an interest attributed to it and is identified by the category of the place. These categories are defined as broad groups to fit several types of places into one category; examples of such categories are airports, restaurants, coffee shops, and museums.

Figure 2-6. MapPoint 2004 Find UI dialog


Using MapPoint 2004, you can find the POI around a location (or around a route) within a specific radius or distance. The location class from the MapPoint 2004 object model exposes the FindNearby method to find the POI around a location.

Let's extend our sample application to find the POI around a location using the FindNearby method. Add a tree view control to add points of interest, a combo box to select distance, and a button to find the POI around a selected location. The new layout is shown in Figure 2-7.

Clicking the Find POI button finds the points of interest around a given location by calling the Location.FindNearby method.

The only parameter that the FindNearby method takes is distance, as type System.Double. The distance must be greater than 0 and less than or equal to 50 miles. The default unit of measurement for distance is miles, but you can change it by setting the appropriate value to the Units property of the ApplicationClass. The Units property is of GeoUnits type, an enumeration containing the values of geoKm and geoMiles. If you want to treat the distances as kilometers, set the Units property to the geoKm value as shown in the following example:

Figure 2-7. Find Place UI Extended for POI


     MapPoint.ApplicationClass app =               new  MapPoint.ApplicationClass( );     app.Units = MapPoint.GeoUnits.geoKm;

The following code shows the actual FindNearby call from the location found during the FindPlaceResults search:

     //Call the find nearby on the current location     MapPoint.FindResults poiResults = location.FindNearby(distance);

The POI search within a one-mile radius around the Space Needle results in 683 POI; the same search with distance unit set to kilometers results in 288 POI. Figure 2-8 shows the POI found within a one-mile radius around the Space Needle.

Figure 2-8. Uncategorized POI around the Space Needle


Going through a list of 683 (or even 288) POI would be annoying, as well as intimidating, so we need a better way of handing the POI to give a better view of the POI search results. This is when the PlaceCategory class comes to our rescue. The place categories are names that can be used to group locations together.

2.2.7.1. Categorizing points of interest using the PlaceCategory class

The PlaceCategory class encapsulates a category name and is exposed as the PlaceCategory property from the Location class. The Parent property of the PlaceCategory gives access to all categories available in MapPoint 2004; there are 48 predefined categories, such as Pharmacies, Restaurants, Theaters, and so on, available in MapPoint 2004. In order to make the POI list more readable by grouping them into meaningful categories, we need to use the PlaceCategory.Name property, which gives the name of the category that a location belongs to. The following code shows how to group locations into categories:

     //Create an object to hold index value     object findResultIndex = null;     //Create a string instance to hold category name     TreeNode node = null;     int nodeCount = 0;     //Create a hashtable to hold category names     Hashtable categoryNames = new Hashtable( );     //Start with index 1 instead of 0     for(int i=1;i<=findResults.Count;i++)     {         //Box the integer value as an object         findResultIndex = i;         //Pass the index as a reference to the get_Item accessor method         MapPoint.Location loc = findResults.get_Item(ref findResultIndex) as          MapPoint.Location;         if(loc.PlaceCategory != null)         {             object nodeIndex = categoryNames[loc.PlaceCategory.Name];             if(nodeIndex == null)             {                 //Create a new category node                 node = new TreeNode(loc.PlaceCategory.Name);                 //Add the current location under this node                 node.Nodes.Add(new TreeNode(loc.Name));                 //Add this node to the tree                 tree.Nodes.Add(node);                 //Store the value in hashtable along with the index number                 categoryNames.Add(loc.PlaceCategory.Name, nodeCount);                 //Increment the node index                 nodeCount ++;             }             else             {                 //Add the current location under this node                 tree.Nodes[Convert.ToInt32(nodeIndex)].Nodes.Add(new TreeNode(loc.Name));             }         }     }

The category name is checked for each POI location; if the category name already exists in the tree view, the current location is added under that category; if that category does not exist in the tree view, a new category node is added before adding the current location. The final application layout is shown in Figure 2-9.

This POI list is easier to navigate than its predecessor in Figure 2-8, but we still have too many unrelated categories. In this case, we can programmatically hide the unwanted place categories.

Figure 2-9. Categorized POI around the Space Needle


2.2.7.2. Controlling place category visibility

The visibility of the point of interest categories can be controlled using the MapPoint 2004 APIs. This PlaceCategories class, which represents the 48 predefined place categories in MapPoint, is exposed as a PlaceCategories property from the Map class. The PlaceCategories class holds the collection of PlaceCategory classes that represent individual categories defined in the MapPoint 2004 points of interest. Set the visibility behavior of an individual place category using the PlaceCategory.Visible property. The following code shows how to block the "RestaurantsOther" category from the POI list:

     //Create an instance of ApplicationClass     app = new MapPoint.ApplicationClass( );     //Define the category that needs to be blocked     string blockCategory = "Restaurants - Other";     for(int i = 1; i<app.ActiveMap.PlaceCategories.Count+1; i++)     {         object index = i;         //if the name of the category matches the block list         //set the visible property to false         MapPoint.PlaceCategory placeCategory =         app.ActiveMap.PlaceCategories.get_Item(ref index) as MapPoint.PlaceCategory;         if(placeCategory.Name == blockCategory)         {             placeCategory.Visible = false;         }         else         {             placeCategory.Visible = true;         }     }

Along similar lines, you can also block multiple categories (presented as an array of strings):

     //Create an instance of ApplicationClass     app = new MapPoint.ApplicationClass( );     //Define the category that needs to be blocked     String[] blockCategoryArray = new string[]                   { "Restaurants - Other", "Museums"};     for(int i = 1; i<app.ActiveMap.PlaceCategories.Count+1; i++)     {         object index = i;         //if the name of the category matches the block list         //set the visible property to false         MapPoint.PlaceCategory placeCategory =         app.ActiveMap.PlaceCategories.get_Item(ref index) as MapPoint.PlaceCategory;         if(Array.IndexOf(blockCategoryArray, placeCategory.Name) >= 0)         {             placeCategory.Visible = false;         }         else         {             placeCategory.Visible = true;         }     }

When changing the visibility of a PlaceCategory, keep in mind that the visibility settings of a category persist between application sessions. If you set a category's visibility to false in one session, you must set it to true to see the category again.


But wouldn't it be more useful to show the distance to each point of interest from the input location? In our example, that would mean showing the distance from the Space Needle to each point of interest in the list.

2.2.8. Calculating Distance Between Two Locations

The Location class has a DistanceTo method that calculates the distance to a given location. Keep in mind that the distance calculated using this method is not the same as the driving distance; this method only gives you the straight line ("as the crow flies") distance between the two locations. The DistanceTo method takes another location as an argument; the following code shows how to calculate the distance between two locations:

     //Get the from location     MapPoint.Location fromLocation             = this.findResults.get_Item(ref fromIndex) as MapPoint.Location;     //Get the to location     MapPoint.Location toLocation             = poiResults.get_Item(ref poiIndex) as MapPoint.Location;     //Calculate the distance between the from location and     //to location using the DistanceTo method      double distance = fromLocation.DistanceTo(toLocation);

Figure 2-10 shows the POI list when it's updated to show the distances from the input location.

Figure 2-10. POI shown with distances


Another way of calculating the distance between two locations is to call the Distance method on an active Map object:

     double distance = app.ActiveMap.Distance(startLocation, endLocation);

Both startLocation and endLocation are MapPoint.Location type objects.

Keep in mind that both these methods calculate the distance based on the units specified at the ApplicationClass level. To change the units of measurement for the distances (between miles and kilometers), use the Units property on the ApplicationClass object.

After displaying the distances in the POI list, it looks much better with all the information needed to decide which points of interest to visit when you are around the Space Needle clearly shown. However, wouldn't it be helpful if you could actually show the POI on a map? After all, what kind of application would MapPoint 2004 be if it didn't actually display a map? For this next step, we need the MapPoint 2004 ActiveX control.




Programming MapPoint in  .NET
Programming MapPoint in .NET
ISBN: 0596009062
EAN: 2147483647
Year: 2005
Pages: 136
Authors: Chandu Thota

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net