Reverse Geocoding with MapPoint 2002
Reverse Geocoding is finding out information about a given coordinate.
This article shows how to determine the country, state, city, nearby
places and maybe even street address for a location known by its
lat/lon.
Where in the world is N47.4560212902604 W122.262495768687 ?
Interactively, it's easy to find out where a spot given by its lat/lon
coordinates is located - just launch MapPoint, press Ctrl-F, switch to
the "Lat/Lon" tab of the Find dialog (enter S and W coordinates as
negative values) and press Enter.
MapPoint will take you to the corresponding spot, and you'll be able
to see at a glance where it is (e.g. in the Location and Scale
toolbar) and what is around it.
But what if you need this sort of information programmatically, e.g. to add
additional info to a list of GPS coordinates captured using a GPS receiver ?
Finding "points of interest" around your given point is relatively
easy - the "FindNearby" method of the location object can be used.
Here's an example:
' Attach to running instance of MapPoint 2002
Set oMpApp = GetObject(, "MapPoint.Application")
' Retrieve the active map
Dim oMap As MapPoint.Map
Set oMap = oMpApp.ActiveMap
' Create location object
Dim oLoc As MapPoint.Location
set oLoc = oMap.GetLocation(47.4560212902604, _
-122.262495768687)
' Find nearby places
Dim oResults as MapPoint.FindResults
Set oResults = oLoc.FindNearby(0.1)
The GetLocation method of the map object is used here to create a
location object from a lat/lon. Then, FindNearby will return all
"points of interest" in a radius of 0.1 mile (or 0.1 km, depening on
your option settings) around the given spot.
FindNearby does this by returning a "FindResults" collection that contains both
Location as well as Pushpin objects.
All that remains to be done is to iterate over the results:
Dim oObj As Object
' Loop over collection
For Each oObj In oResults
MsgBox oObj.Name
Next oObj
There are two problems with this solution, however:
- Displaying just the name of a match is not enough, other data like
the match type or the note attached to a pushpin may be interesting.
As it turns out, the real problem with displaying this sort of
information is that the objects in the "FindResults" collection are
not of the same type - they are a mix of Locations and Pushpins that
support different methods and properties. They happen to share the
"Name" property so the above loop works, but that's about all
interesting properties these two objects share.
- Sometimes more precise information about the location in
question is required than what is just close to it - ideally a
street address of the location itself.
The first of our two problems is solved by differentiating between the
object types in the "FindResults" collection. The
If Typeof Object Is Type Then
construct in VB can be used for this purpose - see the complete sample
below for details
The second problem is a little bit more difficult to solve. MapPoint
does not provide a direct way to convert from a coordinate to an
address. However, the "ObjectsFromPoint" method of the map object is
the programmatic equivalent to the user (double-)clicking on the map -
it will yield a list of potentially interesting objects sorted by
increasing size (or if you prefer, decreasing specificity).
ObjectsFromPoint needs a screen coordinate on input, but that can be
obtained using the "LocationToX" and "LocationToY" methods. Since screen
coordinates are used here, it is important to ensure the map is zoomed to
the location in question - therefore, a height of 1 is used in the
GetLocation method, and the map is centered on the location using its
"GoTo" method.
This is one way to code this (initial code same as above):
set oLoc = oMap.GetLocation(47.4560212902604, _
-122.262495768687, 1)
oLoc.GoTo
' Retrieve ObjectsFromPoint
Dim oResults as MapPoint.FindResults
Set oResults = oMap.ObjectsFromPoint( _
oMap.LocationToX(oLoc), _
oMap.LocationToY(oLoc))
As you can see, ObjectsFromPoint also returns a FindResults collection,
just like FindNearby (and a couple other methods, actually).
The complete sample below illustrates both techniques.
To try it, create a VB project and do the following:
The sample retrieves the lat/lon coordinate entered by the user, and tries
to display a maximum of information about it in the listbox, using both the
"FindNearby" as well as the "ObjectsFromPoint" technique.
The "working horse" that does this is the ShowResults subroutine - it
accepts a title (for the listbox), a FindResults collection, and the
original spot as a location object. The latter is used to compute the distance
from the original spot to the locations MapPoint found - the larger the
distance, the less "specific" the location found probably is.
After adding a title to the list (so that the user can tell apart the
"FindNearby" and the "ObjectsFromPoint" results, ShowResults displays the
ResultsQuality property of the collection. It can have the following
values:
Constant name | Value | Description |
geoAllResultsValid | 0 | Used only for results obtained from the FindNearby and ObjectsFromPoint methods, where all returned results match the method criteria
|
geoAmbiguousResults | 2 | At least the first two results are good matches, but it is not clear which one was intended
|
geoFirstResultGood | 1 | The first result is a good match to the method criteria
|
geoNoGoodResult | 3 | None of the results is a good match to the method criteria, but the results are the best available
|
geoNoResults | 4 | No results
|
With FindNearby and ObjectsFromPoint, I have always only seen quality codes
of either 0 (all valid) or 4 (nothing found) though.
ShowResults then iterates over the objects in the FindResults
collection. Depending on the object type, the following information is added to the list:
- Location object:
- Location name
- Place category (if available)
- Location type code
- Street address (if available)
- Distance to original location
- Pushpin object:
- Pushpin name
- Pushpin note
Place category and location type are of particular interest. The
former provides (textual) information about "nearby places" locations,
e.g. "Hotels and Motels", "Restaurants - Italian". The latter is
numerically coded and describes the type of object you found - for
example, 19 means "country", 18 means state (or similar subdivision,
e.g. région in France or Bundesland in Germany), 17 means county (or
département in France, Landkreis in Germany etc.)
Check out the
GeoShowDataBy values in MapPoint help for a detailed description
of these codes.
Please find the complete sample code below.
Mapping and especially GPS-related topics are a hobby - Gilles enjoys developing solutions for Microsoft MapPoint and his favorite outdoor occupation is confluence hunting.