Section 2.5. Dealing with Latitude and Longitude


2.5. Dealing with Latitude and Longitude

You know how to find a location using a place name or an address, but do you know how to find a location using latitude and longitude? Using the Map class's GetLocation method, you can easily find a location that corresponds to a given latitude and longitude measurement. This is also called geocoding in cartography terminology. This method takes latitude and longitude as System.Double values and returns a Location instance that represents the input latitude and longitude. This method also takes the altitude as an argument, but it is mainly used at the time when the location is displayed on a map, so you can freely pass one mile for the time being. The following code shows how to find a location using latitude and longitude:

     //Get the reference to the active map instance     MapPoint.Map map = app.ActiveMap;     //Call the GetLocation method     to find location     //using the latitude and longitude     MapPoint.Location location =             m.GetLocation(41.33896, -122.43433, 1);

At this point, don't bother to get the street address for the location returned by the GetLocation method because this method doesn't return the address all the time. Don't be disappointed, as there is still a way to find the nearest address using the current location. The idea is to basically do a hit-detection around the found location to see if there are any addresses available. Before we get into the details of how to find out a location's address, let's look at the hit-detection in MapPoint 2004 in detail.

2.5.1. Hit-Detection in MapPoint 2004

What is hit-detection in MapPoint 2004, and how do you programmatically implement it? The Map object in MapPoint has the method, ObjectsFromPoint, which allows you to perform a hit-detection around any given point (x and y coordinates) on the screen. You can already get a point from any given location, so what does this method return? As the method name suggests, it returns an array of objects wrapped in a FindResults instance. The type of objects returned by this method depends on the current map altitude. For example, if you call this method at lower altitudes, it returns locations with street addresses; if you go to higher altitudes and call this method, it returns larger geographic areas, such as Zip Code, county, and time zone of the point. The following snippet shows how to call the ObjectsFromPoint method for any given Location:

     //Get Location from latitude and longitude     MapPoint.Location location =            app.ActiveMap.GetLocation(mylatitude, mylongitude, altitude);     /Now use the Map.ObjectsFromPoint method         to get points from the     //above location     MapPoint.FindResults findresults =          app.ActiveMap.ObjectsFromPoint(                 app.ActiveMap.LocationToX(location),                 app.ActiveMap.LocationToY(location));

The ObjectsFromPoint method is very versatile and can be used for many purposes, such as querying for address of a given location, determining time zone, querying a territory, and so on. In the following sections, I will show you how to use the ObjectsFromPoint method in a few of these scenarios.

2.5.2. Determining Time Zone for a Given Location

Determining the time zone of any location can be done using the ObjectsFromPoint method. When this method is called at lower altitudes (usually around two to three miles), it returns the time zone as one of the FindResults objects. Using this technique, you can check whether FindResults contains a time zone by looking for the string "GMT" in the name of the each found result:

     string place = "Redmond, WA";     //Find the location first     MapPoint.FindResults findResults         = axMappointControl1.ActiveMap.FindResults(place);     if(findResults != null && findResults.Count > 0)      {       object index = 1;       MapPoint.Location location =       findResults.get_Item(ref index) as MapPoint.Location;       //Zoom into it       location.GoTo( );       //Set low altitudes       axMappointControl1.ActiveMap.Altitude = 2;      //Now get points from the location      MapPoint.FindResults points          = axMappointControl1.ActiveMap.ObjectsFromPoint(               axMappointControl1.ActiveMap.LocationToX(location),               axMappointControl1.ActiveMap.LocationToY(location));      if(points != null && points.Count > 0)       {         for(int i=1;i<=points.Count;i++)         {          object index2 = i;          //Get location          MapPoint.Location loc           = points.get_Item(ref index2) as MapPoint.Location;         //Look for GMT in the name of the location         if(loc.Name.IndexOf("GMT") > 0)         {           MessageBox.Show(loc.Name);           break;          }        }      }

As an example, when this code is executed, the time zone of the New York area is displayed as "Eastern (GMT-5)."

Note that if you are using a non-North American version of MapPoint, the localized string to match may be different from GMT.


Next, let's see how we can extend the ObjectsFromPoint method to determine the street address of a location.

2.5.3. Determining the Street Address of a Given Location

One of the limitations of the GetLocation method is that you cannot always get the address for a given set of latitude and longitude. The workaround for this limitation is to use the hit-detection technique around the given latitude and longitude.

There are a few ways to do the hit-detection:

  • Panning around at the same altitude to see whether we find street addresses

  • Zooming in and out trying to find locations with street addresses

  • Routing to a place with a known street address (such as the Space Needle) so that the found location automatically snaps to the nearest street

Due to its efficiency and accuracy, I choose to implement the first option, panning around to see whether there is a nearby street. The basic approach to panning around the chosen found location is to move in a general spiral. In this case, the center of the spiral goes to the original location found using the GetLocation method, and I continue increasing the radius until I find a street address. The implementation of this approach is as follows:

     public static MapPoint.Location GetLocationEx(double latitude,                                     double longitude, ref MapPoint.Application app)     {         if(app == null)             return null;         //Define the altitude         double altitude = 3;         //Flag to indicate that a street address is found         bool found = false;         //Original latitude and longitude         double mylatitude = latitude;         double mylongitude = longitude;         //Angle to create a spiral         double theta = 0;         //Radius of the spiral         double radius = 0.00003;         //flag to indicate the original location         bool first = true;         //Define a location to hold end-result         MapPoint.Location foundLocation = null;         //Approximately corrects for latitude changing the value of longitude         double latitudeInRadians = latitude * Math.PI / 180;         double longMultiplier = 1 / Math.Cos(latitudeInRadians);         //Get the location using the Map.GetLocation method   with the given         //latitude and longitude         //The altitude plays an important role in getting the better accurate         //addresses for given lat longs         while(!found)         {             MapPoint.Location location =                    app.ActiveMap.GetLocation(mylatitude, mylongitude, altitude);             if(location == null)                 return null;             if(first)             {                 //Zoom map to the original location                 location.GoTo( );                 first = false;             }             //Now use the Map.ObjectsFromPoint method to get points from the             //current map center             MapPoint.FindResults findresults =                 app.ActiveMap.ObjectsFromPoint(                             app.ActiveMap.LocationToX(location),                             app.ActiveMap.LocationToY(location));             //Select a point that has street address and return that location             object index = null;             //Now loop through the results             for(int i = 0; i<findresults.Count; i++)             {                 index = i+1;                 MapPoint.Location loc =                           findresults.get_Item(ref index) as MapPoint.Location;                 //Check for the street names                 if(loc != null && loc.StreetAddress != null)                 {                     //Found the steet name                     foundLocation = loc;                     found = true;                 }             }             //Radius increment value; if you want your             //Street address find to be more accurate, keep this             //value at either 0.00001 or 0.00002, but keep             //in mind that lower values may take more time to resolve             Double accuracy = 0.00004;             //Increment the radius             radius = radius + accuracy;             //Increment the angle             theta = theta + Math.PI/16;             //Pan to next latitude, longitude             mylongitude = longitude + (longMultiplier * (Math.Cos(theta) * radius));             mylatitude = latitude + Math.Sin(theta) * radius;         }         return foundLocation;     }

An example of how the above algorithm works is shown in Figure 2-16 on a map with blue and red pushpins. The center of the spiral is the original location found for a given latitude and longitude; the pushpin to its right shows the nearest street address found using the spiral method.

You could enhance this algorithm by completing the circle (with no increments to radius) and seeing whether there is more than one intersection between the circle and a street; if there is, the midpoint of that arc would be a closer point to the original location.

Figure 2-16. Finding the nearest street address from a Lat/Long algorithm


The location found using the previously described method can be used to find the nearest street address for a given latitude and longitude. You can find this method in the ProgrammingMapPointUtilities project in the Chapter 02 file included in the companion material.

Finally, if you are using the ShowFindDialog method for finding latitude and longitude, use the GeoFindState.geoFindLatLong as FindState parameter; in this scenario, the method looks for a comma as a delimiter to parse the values correctly. Anything that lies to the left of the delimiter is considered latitude, and the value that lies to the right of the delimiter is considered longitude.




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