The Map Suite Routing Extension QuickStart Guide will guide you through the process of creating a simple routing application and will help you become familiar with Map Suite Routing. This edition of the QuickStart Guide supports Map Suite Routing 3.0.375 or higher, and shows you how to create a Winforms application. Note that to use the Routing Extension, the .NET Framework 3.5 and a Map Suite GIS component (Desktop, Web, Silverlight or Services Edition) version 3.0 or higher are required.
Download Sample Code From This Exercise - C#
Welcome to Map Suite Routing from ThinkGeo, a full-featured extension of our Map Suite mapping controls that makes it easy for any Microsoft .NET developer to add routing features to a Map Suite-enabled Microsoft .NET application quickly and efficiently. Using the intuitive object model, even developers inexperienced in Geographic Information Systems (GIS) can have fully functional maps working in minutes.
The Map Suite Routing Extension provides interfaces and classes for determining the shortest or fastest route between two points, with the ability to add more routing options. You can retrieve the roads collection consisting of routes, turn-by-turn directions, as well as other information like total distance. You can also utilize many additional features, such as getting a service area around a location, adding sequential intermediate points, or making the route avoid certain areas or features.
The purpose of this guide is to help you get started building your own routing applications. Like any new software, there is some learning to be done.
(For the purpose of this guide, let's assume that we have installed the Map Suite Routing Evaluation Edition 3.0 to the default folder "C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0 (BETA)".
Setting up the Environment
Let's start a new Windows Forms Application project in the Visual Studio .NET 2008 IDE and call it "HelloWorld" (see Figure 1). Set the Templates to ".NET Framework 3.5" for the project.

Figure 1. Create a new Windows Forms project in Visual Studio .NET 2008 IDE.
The project "HelloWorld" is created in a new solution called "HelloWorld". The wizard creates a single Windows Form.
Adding the Map Control to the Visual Studio .NET IDE Toolbox
1. When you first open the Visual Studio .NET IDE after installing Map Suite, you may not see the Map Suite Desktop Edition's map control in the Toolbox. In this case, you will need to perform the following steps to add it.
Hover on the Toolbox and right click anywhere on the list of controls. You will get a pop-up menu. Select "Choose items..."

2. The Choose Toolbox Items dialogue will appear. You will need to select the ".NET Framework Components" tab and then click the "Browse..." button. Finally, navigate to the "C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\Developer Reference\MapSuite Routing\" folder and select the DesktopEdition.dll.

3. You should now have the Map control available in your Toolbox as shown below.

Figure 2. The Desktop Edition's Map Control in the Toolbox window.
Draw the Map control on the form by clicking on the Map control in the Toolbox and then dragging the map onto the form. You can also size the map to your desired width and height. You can leave the name of Map control as winformMap1.

Adding References to the Map Suite Routing "Hello World" Sample
We now have the DesktopEdition.dll referenced. Next, we need to add MapSuiteCore.dll and MapSuiteRouting.dll to the references. Right-click the project in the Solution Explorer and select "Add Reference...", navigate to the "C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\Developer Reference\MapSuite Routing" folder and select those two files.

Now we are ready to add code.
Map Suite Routing Extension "Hello World" Sample
After this section, you will be able to draw a map with the Map control and find the route using your own data. To begin, let's have a look at how to prepare the routing data.
Prepare Routing Data
The Map Suite Routing Extension supports multiple kinds of data sources, such as SQL Server 2008, Postgre Database, Oracle, etc., but they must include LineShape data only. We'll use a Shape File as the data source for this sample. First, though, we need to build the routing index file based on it.
Build the routing index file (.rtg/.rtx) using the included Map Suite Routing Explorer tool. (See Figure 4)

Figure 3. Building the routing index file with Map Suite Routing Explorer.
(NOTE: The full path to the Shape File we are creating the routing data for is "C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp", and the default path for the routing data is the same folder as the Shape File.)
Map Suite Routing Extension "Hello World"
1. Our first step is to define the renderers for the map, route and stops. Let's assume we need to find the shortest route between the two roads with the feature IDs "4716" and "9638." Below is the code that will make this happen. All of the following is written in the Form1_Load event of the windows form. Also, you'll need to add the namespaces used as such: "using ThinkGeo.MapSuite.Core;", "using ThinkGeo.MapSuite.DesktopEdition;" and "using ThinkGeo.MapSuite.Routing;".
private void Form1_Load(object sender, EventArgs e)
{
// Set the Map Unit and current extent
winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
winformsMap1.CurrentExtent = new RectangleShape(-97.7970203443604, 30.3231958204346, -97.6787456556397, 30.2358201795654);
// Define a new layer to render the the Austin streets
ShapeFileFeatureLayer austinStreetsLayer = new ShapeFileFeatureLayer(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp ");
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.LocalRoad4;
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay austinStreetOverlay = new LayerOverlay();
austinStreetOverlay.Layers.Add("austinStreetsLayer", austinStreetsLayer);
winformsMap1.Overlays.Add("austinStreetOverlay", austinStreetOverlay);
// Define a Routing layer to render the route and stops
RoutingLayer routingLayer = new RoutingLayer();
austinStreetsLayer.Open();
routingLayer.StartPoint = austinStreetsLayer.FeatureSource.GetFeatureById("4716", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
routingLayer.EndPoint = austinStreetsLayer.FeatureSource.GetFeatureById("9638", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
austinStreetsLayer.Close();
LayerOverlay routingOverlay = new LayerOverlay();
routingOverlay.Layers.Add("RoutingLayer", routingLayer);
winformsMap1.Overlays.Add("RoutingOverlay", routingOverlay);
winformsMap1.Refresh();
}
(NOTE: The data used in the sample can be found in the installation folder under "C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData".)
Figure 4 shows what you'll see when you run your application.

Figure 4. Initialize the map for finding a route.
2. Find the shortest route and render it on the map.
Add a button named "Find The Shortest Path" and double-click it to add the click event. Next, enter the code below to find the shortest route and render it on the map.
private void button1_Click(object sender, EventArgs e)
{
ShapeFileFeatureSource featureSource = new ShapeFileFeatureSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp");
RtgRoutingSource routingSource = new RtgRoutingSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.rtg");
RoutingEngine routingEngine = new RoutingEngine(routingSource, featureSource);
RoutingLayer routingLayer = (RoutingLayer)((LayerOverlay)winformsMap1.Overlays["RoutingOverlay"]).Layers["RoutingLayer"];
winformsMap1.Overlays["RoutingOverlay"].Lock.EnterWriteLock();
try
{
routingLayer.Routes.Clear();
routingLayer.Routes.Add(routingEngine.GetRoute("4716", "9638").Route);
}
finally
{
winformsMap1.Overlays["RoutingOverlay"].Lock.ExitWriteLock();
}
winformsMap1.Refresh();
}
Run the sample and click the "Find The Shortest Path" button. You will see the result as shown in Figure 5.

Figure 5. The shortest path between points has been generated.
(NOTE: We can also use InMemoryFeatureLayer to render the routing result; RoutingLayer is just a shortcut to make it more convenient.)
Finding The Shortest Path Using Coordinates
The Map Suite Routing Extension also supports finding a route between specified coordinates. Below is the sample code that will make this happen.
private void Form1_Load(object sender, EventArgs e)
{
// Set the Map Unit and current extent
winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
winformsMap1.CurrentExtent = new RectangleShape(-97.7970203443604, 30.3231958204346, -97.6787456556397, 30.2358201795654);
// Define a new layer to render the the Austin streets
ShapeFileFeatureLayer austinStreetsLayer = new ShapeFileFeatureLayer(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp");
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.LocalRoad4;
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay austinStreetOverlay = new LayerOverlay();
austinStreetOverlay.Layers.Add("austinStreetsLayer", austinStreetsLayer);
winformsMap1.Overlays.Add("austinStreetOverlay", austinStreetOverlay);
// Define a Routing layer to render the path and stops
RoutingLayer routingLayer = new RoutingLayer();
austinStreetsLayer.Open();
// The code that routes using coordinates
routingLayer.StartPoint = new PointShape(-97.763184, 30.299407);
routingLayer.EndPoint = new PointShape(-97.713382, 30.259609);
austinStreetsLayer.Close();
LayerOverlay routingOverlay = new LayerOverlay();
routingOverlay.Layers.Add("RoutingLayer", routingLayer);
winformsMap1.Overlays.Add("RoutingOverlay", routingOverlay);
winformsMap1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
ShapeFileFeatureSource featureSource = new ShapeFileFeatureSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp");
RtgRoutingSource routingSource = new RtgRoutingSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.rtg");
RoutingEngine routingEngine = new RoutingEngine(routingSource, featureSource);
RoutingLayer routingLayer = (RoutingLayer)((LayerOverlay)winformsMap1.Overlays["RoutingOverlay"]).Layers["RoutingLayer"];
winformsMap1.Overlays["RoutingOverlay"].Lock.EnterWriteLock();
try
{
routingLayer.Routes.Clear();
routingLayer.Routes.Add(routingEngine.GetRoute(routingLayer.StartPoint, routingLayer.EndPoint).Route);
}
finally
{
winformsMap1.Overlays["RoutingOverlay"].Lock.ExitWriteLock();
}
winformsMap1.Refresh();
}
Now, you will see the same result as in Figure 5 after running.
Adding Sequential Intermediate Stops
With the help of a Routing Layer, it's easier to add sequential intermediate stops. Let's define two intermediate stops whose feature ids are "5137" and "8179." Use the code below to accomplish this.
private void Form1_Load(object sender, EventArgs e)
{
// Set the Map Unit and current extent
winformsMap1.MapUnit = GeographyUnit.DecimalDegree;
winformsMap1.CurrentExtent = new RectangleShape(-97.7970203443604, 30.3231958204346, -97.6787456556397, 30.2358201795654);
// Define a new layer to render the the Austin streets
ShapeFileFeatureLayer austinStreetsLayer = new ShapeFileFeatureLayer(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp");
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.LocalRoad4;
austinStreetsLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
LayerOverlay austinStreetOverlay = new LayerOverlay();
austinStreetOverlay.Layers.Add("austinStreetsLayer", austinStreetsLayer);
winformsMap1.Overlays.Add("austinStreetOverlay", austinStreetOverlay);
// Define a Routing layer to render the path and stops
RoutingLayer routingLayer = new RoutingLayer();
austinStreetsLayer.Open();
routingLayer.StartPoint = austinStreetsLayer.FeatureSource.GetFeatureById("4716", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
PointShape stopPoint1 = austinStreetsLayer.FeatureSource.GetFeatureById("5137", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
PointShape stopPoint2 = austinStreetsLayer.FeatureSource.GetFeatureById("8179", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
routingLayer.StopPoints.Add(stopPoint1);
routingLayer.StopPoints.Add(stopPoint2);
routingLayer.EndPoint = austinStreetsLayer.FeatureSource.GetFeatureById("9638", ReturningColumnsType.NoColumns).GetShape().GetCenterPoint();
austinStreetsLayer.Close();
LayerOverlay routingOverlay = new LayerOverlay();
routingOverlay.Layers.Add("RoutingLayer", routingLayer);
winformsMap1.Overlays.Add("RoutingOverlay", routingOverlay);
winformsMap1.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
ShapeFileFeatureSource featureSource = new ShapeFileFeatureSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.shp");
RtgRoutingSource routingSource = new RtgRoutingSource(@"C:\Program Files\ThinkGeo\Map Suite Routing Evaluation Edition 3.0(BETA)\HowDoISamples\SampleData\Austinstreets.rtg");
RoutingEngine routingEngine = new RoutingEngine(routingSource, featureSource);
RoutingLayer routingLayer = (RoutingLayer)((LayerOverlay)winformsMap1.Overlays["RoutingOverlay"]).Layers["RoutingLayer"];
winformsMap1.Overlays["RoutingOverlay"].Lock.EnterWriteLock();
try
{
routingLayer.Routes.Clear();
// Generate all key points
Collection<PointShape> keyPoints = new Collection<PointShape>();
keyPoints.Add(routingLayer.StartPoint);
foreach (PointShape stop in routingLayer.StopPoints)
{
keyPoints.Add(stop);
}
keyPoints.Add(routingLayer.EndPoint);
// Get the path for each segment between two key points
for (int i = 0; i < keyPoints.Count - 1; i++)
{
routingLayer.Routes.Add(routingEngine.GetRoute(keyPoints<i>, keyPoints[i + 1]).Route);
}
}
finally
{
winformsMap1.Overlays["RoutingOverlay"].Lock.ExitWriteLock();
}
winformsMap1.Refresh();
}
(NOTE: Here we also need to have a “using Collections.ObjectModel” added to the application.)
Let's run the application and click the "Find The Shortest Path" button. You will see the path and stops rendered on the map as shown in Figure 6.

Figure 6. Finding path with intermediate stops.
(NOTE: The Map Suite Routing Extension doesn't support finding a path between Matrix points (Points-to-Points Route), so the intermediate stops must be added in order.)
Summary
You now know how to use the Map Suite Routing Extension to find the shortest route. Let’s recap what we have learned about the objects' relationships and how the pieces of Map Suite work together:
- It is of the utmost importance to make sure the features in the routing data source (including Shape Files and other data sources like Oracle, Postgre Database, SQL Server 2008, etc.) are LineShapes.
- The RoutingEngine is the main class that contains all of the other objects that define how to find a route.
- The RoutingLayer is a convenient class for finding and rendering a route. It allows us to add sequential intermediate stops.
If you have questions about anything covered in this QuickStart Guide, the ThinkGeo Support Team is ready and available to help. If we can be of any assistance, please contact us using one of the methods below:
Free Discussion Forums:
ThinkGeo Discussion Forums
Pre-Sales & Customer Support:
ThinkGeo Customer Portal
Support Phone:
1-866-847-7510
1-785-727-4133 (Outside North America)
Web Site:
http://thinkgeo.com
Download Sample Code From This Exercise - C#