About routing in the MapPoint object model
Routing is a powerful part of MapPoint, and you can access all of that power through automation.
MapPoint has one Route object that is in use at all times. To get directions from one place to another, or to highlight those directions on the screen, you must make modifications to that route. A route is made up of a start point, an end point, and zero or more stops along the way. Collectively, these are referred to as waypoints. Changing a route mostly consists of modifying the waypoints that make up the route. You can clear the route of all waypoints, add or remove individual waypoints, or change the order of waypoints in the route.
You can access the Route object through the ActiveRoute property of the Application object.
Modifying the waypoints in a route
Once you have the Route object, the most common way to modify the route is to change the list of waypoints that it contains. Waypoint objects are created by specifying a Location or Pushpin object that defines a start point, an end point, or stop along the route. See About locations in the MapPoint object model for more information on Pushpins and locations.
If you are creating a new route, you must clear the current route first (more than one route is not allowed in the map at a given time), using the Clear method on the Route object.
The following example creates a new route by adding waypoints:
Sub AddWaypoints()
Dim oMap As MapPoint.Map
Dim oRte As MapPoint.Route
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
Set oRte = oMap.ActiveRoute
oRte.Clear
With oRte.Waypoints
.Add oMap.FindAddressResults(, "New Bedford", , _
"Mass")(1)
.Add oMap.FindAddressResults(, "Newport", , "RI")(1)
.Add oMap.FindAddressResults(, "Mystic", , "Conn")(1)
End With
oRte.Calculate
'Zoom to the route
oRte.Directions.Location.GoTo
End Sub
Note The Clear method is also the easiest way to remove the route from the map. You cannot delete the Route object; you simply remove all waypoints from it so that it will not appear.
When you have finished modifying the route's waypoints, you must calculate the route in order for directions and other properties of the route to be generated. To find out whether a route is calculated, use the IsCalculated property. The Directions collection of the route is the storage of the final turn-by-turn directions and gives you useful properties and methods of the route, such as the location, which is used here to zoom to the entire route. The Directions collection and Direction objects are discussed in more detail later in "Getting driving directions."
Note The Calculate method requires some processing time and takes a longer time depending on how complicated and long the route is. It is a good idea to optimize your code so that you do not needlessly call the Calculate method too many times. For example, you do not need to call the Calculate method after adding each waypoint. It is a good idea to finish modifying your route completely before calling the Calculate method.
Waypoints can also be created from Pushpins. The Pushpins can come from any data set, including imported and linked sets. The following example imports one of the sample files and adds a subset of the Pushpins as stops. This example uses the QueryCircle method to obtain a list of records, which is a Recordset object that can be used to add Waypoint objects to the route. Any of the query methods (QueryAllRecords, QueryCircle, and QueryShape) can be substituted here.
Note This sample assumes that there is a MyData.mdb file with an Employees table. For this code to work properly, the table must be imported as a Pushpin map. You can modify the names and paths in this code to make it work with your data.
Sub AddPPWaypoints()
Dim oApp As MapPoint.Application
Set oApp = GetObject(, "MapPoint.Application")
oApp.PaneState = geoPaneRoutePlanner
' Ensure we're working in miles
oApp.Units = geoMiles
Dim oMap As MapPoint.Map
Set oMap = oApp.ActiveMap
Dim strDB As String
strDB = App.Path & "\MyData.MDB!Employees"
' Add all local addresses as waypoints
Dim dsEmps As MapPoint.DataSet
Set dsEmps = oMap.DataSets.ImportData(strDB)
Dim oLoc As MapPoint.Location
Set oLoc = oMap.FindResults("Seattle, WA")(1)
oLoc.GoTo
' Find all employees within 20 miles of Seattle
Dim rsEmps As MapPoint.Recordset
Set rsEmps = dsEmps.QueryCircle(oLoc, 20)
' Add those addresses as Waypoints
Dim oWps As MapPoint.Waypoints
Set oWps = oMap.ActiveRoute.Waypoints
Do While Not rsEmps.EOF
If (rsEmps.IsMatched) Then
oWps.Add rsEmps.Pushpin
End If
rsEmps.MoveNext
Loop
oMap.ActiveRoute.Calculate
' How many did we get?
MsgBox oWps.Count
End Sub
You can move Waypoint objects by setting their Anchor property, which is the Pushpin or Location object with which the Waypoint object is associated. If a Waypoint object is anchored to a Pushpin and the Pushpin is moved, then the Waypoint object moves with the Pushpin.
Sub MoveWaypoint()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
' Zoom in on the area
oMap.FindResults("Rhode Island, USA")(1).GoTo
With oMap.ActiveRoute.Waypoints
Dim oWP As MapPoint.Waypoint
Set oWP = .Add(oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1), "First Stop")
MsgBox "The waypoint will be moved after this message."
Set oWP.Anchor = oMap.FindAddressResults(,_
"Newport", , "RI")(1)
End With
oMap.ActiveRoute.Calculate
End Sub
To remove a waypoint from the route, simply call the Delete method on the Waypoint object.
Sub DeleteWaypoint()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
With oMap.ActiveRoute.Waypoints
Dim oWP As MapPoint.Waypoint
Set oWP = .Add(oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1), "First Stop")
oMap.ActiveRoute.Calculate
MsgBox "The waypoint will be deleted after this message."
oWP.Delete
End With
oMap.ActiveRoute.Calculate
End Sub
You can reorder Waypoint options individually using the Reorder method or the ListPosition property:
Sub ReorderWaypoints()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
' Zoom in on the area
oMap.FindResults("Massachusetts, USA")(1).GoTo
With oMap.ActiveRoute.Waypoints
.Add oMap.FindAddressResults(, "Boston", , "Mass")(1)
.Add oMap.FindAddressResults(, "Newport", , "RI")(1)
.Add oMap.FindAddressResults(, "New Bedford", , _
"Mass")(1)
.Add oMap.FindAddressResults(, "Mystic", , "Conn")(1)
oMap.ActiveRoute.Calculate
MsgBox _
"The stops will switch position after this message."
' Make Newport the third stop
.Item(2).ListPosition = 3
oMap.ActiveRoute.Calculate
MsgBox "The start and end points will switch after this message."
' Reverse the top and bottom
.Item(4).Reorder geoMoveToTop
.Item(2).Reorder geoMoveToBottom
oMap.ActiveRoute.Calculate
End With
End Sub
Note In the preceding code, the route is calculated three times. This is unnecessary in practice but provides a useful example because you can see the route being re-created with the new waypoint order on the screen.
You can also have MapPoint automatically reorder the route to create a shorter, more efficient trip by optimizing the route. Optimizing changes the order of the stops, but does not affect the start and end points. It will not have an effect on trips with less than four waypoints. The following code sample uses the Optimize method to optimize stops:
Sub OptimizeWaypoints()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
' Zoom in on the area
oMap.FindResults("Massachusetts, USA")(1).GoTo
With oMap.ActiveRoute.Waypoints
.Add oMap.FindAddressResults(, "Boston", , "Mass")(1)
.Add oMap.FindAddressResults(, "Newport", , "RI")(1)
.Add oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1)
.Add oMap.FindAddressResults(, "Mystic", , "Conn")(1)
.Optimize
End With
oMap.ActiveRoute.Calculate
End Sub
Note Optimizing can be a time-intensive process, especially as the number of stops that you are optimizing increases. It is a good idea to manage your code so that you do not have to optimize unnecessarily. For example, do not optimize after adding each waypoint. Also, notice that the route does not need to be calculated to optimize the waypoints.
Modifying the route in other ways
Changing waypoints is not the only way that you can modify a route. You can also specify arrival, wait, and departure times for each waypoint, as well as areas to avoid and general preferences for specific drivers.
The following example specifies the preferred departure time for the starting waypoint and the duration of time that will be spent at the first stop. Just as in the user interface, MapPoint will attempt to accommodate your time preferences when calculating the route, but it cannot always use these preferences. For example, if you set the departure time from the first stop at 10:00 A.M. and the arrival time for the next stop at 10:10 A.M. when there is a 30-minute drive between them, MapPoint will not be able to create the route using those preferences.
Note Time intervals are represented in fractional days. You can use the GeoTimeConstants geoOneHour and geoOneMinute to calculate the time intervals.
Sub WaypointTimes()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
With oMap.ActiveRoute.Waypoints
Dim oWP As MapPoint.Waypoint
.Add oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1)
.Add oMap.FindAddressResults(, "Newport", , "RI")(1)
.Add oMap.FindAddressResults(, "Mystic", , "Conn")(1)
.Item(1).PreferredDeparture = "10:00 AM"
.Item(2).StopTime = 3 * geoOneHour
End With
oMap.ActiveRoute.Calculate
End Sub
Note You can specify the time you want to depart, arrive, or stop at a particular waypoint. You can't set the arrival time for the start waypoint or the departure time for the end waypoint.
You can create a detour around an area by creating a rectangle Shape object and setting its Avoided property to True. The following is an example of creating and using an avoided area:
Sub AvoidArea()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
Dim locFallRiver As MapPoint.Location
Set locFallRiver = oMap.FindAddressResults(,_
"Fall River", , "Mass")(1)
locFallRiver.GoTo
' Create an avoided area
Dim oDetour As MapPoint.Shape
Set oDetour = oMap.Shapes.AddShape(geoShapeRectangle, _
locFallRiver, 4, 4)
oDetour.Name = "Detour"
oDetour.Avoided = True
With oMap.ActiveRoute
Dim oWP As MapPoint.Waypoint
.Waypoints.Add oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1)
.Waypoints.Add oMap.FindAddressResults(,_
"Newport", , "RI")(1)
.Calculate
End With
End Sub
To remove a detour, simply call the Delete method on the Shape object or set the Avoided property to False. Removing a detour will invalidate the directions, so they will need to be recalculated.
You can also modify the way that a route is calculated by changing the driver profile. These profile settings include average driving speed, rest stop options, road preferences, how costs are calculated, size of the car's fuel tank, and other properties that may affect how the route is created. These settings can be accessed via the DriverProfile object. The following example sets the driving day from 8:00 A.M. to 7:00 P.M. with 45-minute rest breaks every four hours.
Note Time intervals are represented in fractional days. Use the GeoTimeConstants geoOneHour and geoOneMinute to calculate the time intervals.
Sub DefineDrivingDay()
Dim oApp As MapPoint.Application
Set oApp = GetObject(, "MapPoint.Application")
Dim oDrvProf As MapPoint.DriverProfile
Set oDrvProf = oApp.ActiveMap.ActiveRoute.DriverProfile
oDrvProf.StartTime = "8:00 AM"
oDrvProf.EndTime = "7:00 PM"
oDrvProf.IncludeRestStops = True
oDrvProf.TimeBetweenRests = 4 * geoOneHour
oDrvProf.RestStopDuration = 45 * geoOneMinute
End Sub
Getting driving directions
Now that you can create a route that matches your set of stops and preferences, you need to create the actual driving directions. Driving directions are generated when you call the Calculate method. Driving directions include summary information, such as DrivingTime, TripTime, Distance, and Cost properties, which are accessed through the Route object. It also includes detailed driving directions, which are accessed through the Directions property. Detailed directions can be accessed for the entire route or just a route segment (the portion of a route between two consecutive waypoints). To access the directions for the entire route, use the Directions property of the Route object. To access the directions for a specific route segment of the route, use the SegmentDirections property for the Waypoint object that begins that segment.
The following code creates a route and then displays the calculated cost of the trip:
Sub CalcRoute()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
With oMap.ActiveRoute
.Waypoints.Add oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1)
.Waypoints.Add oMap.FindAddressResults(,_
"Newport", , "RI")(1)
.Calculate
MsgBox Format(.Cost, "$.00")
End With
End Sub
To hide or show the Directions pane in the user interface, which includes the route directions, use the ItineraryVisible property.
Sub ItineraryPaneToggle()
Dim oApp As MapPoint.Application
Set oApp = GetObject(, "MapPoint.Application")
' Switch the state
oApp.ItineraryVisible = Not oApp.ItineraryVisible
End Sub
To expand or collapse directions, use the Expanded property of the Directions collection.
Direction objects and Directions collections are only valid while the itinerary that they were created with is current. Any action that changes the itinerary for a route (such as moving or adding Waypoint objects) will invalidate any Direction objects that are being accessed (such as in a variable or in a Visual Basic collection). A new Direction object must be obtained after the route is recalculated. It is therefore not advisable to cache Direction objects.
To programmatically view the directions information in automation, use the Directions collection, which contains detailed information about the calculated route. The following example shows how to access this information.
Sub DirectionProps()
Dim oMap As MapPoint.Map
Set oMap = GetObject(, "MapPoint.Application").ActiveMap
oMap.Parent.PaneState = geoPaneRoutePlanner
With oMap.ActiveRoute
Dim oWP As MapPoint.Waypoint
.Waypoints.Add oMap.FindAddressResults(,_
"New Bedford", , "Mass")(1)
.Waypoints.Add oMap.FindAddressResults(,_
"Newport", , "RI")(1)
.Calculate
MsgBox .Directions(1).StartTime & ": " & _
.Directions(1).Instruction
End With
End Sub
The Action property returns the action for a specified direction (such as turn left, enter roundabout, and so on), and the Type property returns the type of the direction (such as rest break, fuel stop, driving instruction, and so on).
The Directions collection and Direction object each have a Location property. This location has the "best map view" of the route, segment, or single direction that the object represents. Use this to zoom to an entire route, segment, or single direction. For more information on best map views, see Working with locations and finding places and address in the MapPoint object model.
More information
About the Microsoft MapPoint object model
What's new for Microsoft MapPoint 2004 developers
Getting started with the MapPoint object model
Getting started with the MapPoint Control
About mapping data with the MapPoint object model
About locations in the MapPoint object model
About shapes in the MapPoint object model