ArcObjects Library Reference  

RoutingForm

About the StreetMap routing Sample

[C#]

RoutingForm.cs

using System;

using System.Windows.Forms;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Catalog;
using ESRI.ArcGIS.CatalogUI;
using ESRI.ArcGIS.Location;
using ESRI.ArcGIS.LocationUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Display;

namespace RoutingSample
{
	public partial class RoutingForm : System.Windows.Forms.Form
	{

	#region  Windows Form Designer generated code 

		public RoutingForm() : base()
		{

			//This call is required by the Windows Form Designer.
			InitializeComponent();

			m_dlgDirections = new DirectionsForm();
			m_dlgRestrictions = new RestrictionsForm();
		}

	#endregion

	#region Form Buttons Events Handlers

		// Just hides form on closing
		private void RoutingForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			e.Cancel = true;
			this.Hide();

			// Bug workaround.
			// ArcMap can lose focus after form closing. SetFocus prevents it.
			SetFocus(m_application.hWnd);
		}

		// Bug workaround.
		// Allows Tab and Escape buttons using in form
		private void RoutingForm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
		{
			if (! this.Modal)
			{
				if (e.KeyCode.Equals((Keys.Tab)))
				{
					e.Handled = true;
					this.ProcessTabKey(! (e.Modifiers == Keys.Shift));
				}
				else if (e.KeyCode.Equals((Keys.Escape)))
					this.Close();
			}
		}

		// Bug workaround.
		// Allows Tab button using in form
		protected override bool ShowFocusCues
		{
			get
			{
				if (this.Modal)
					return base.ShowFocusCues;
				else
					return true;
			}
		}

		private void m_btnRoutingService_Click(object sender, System.EventArgs e)
		{
			OpenRoutingService();
		}

		private void m_btnAddressLocator_Click(object sender, System.EventArgs e)
		{
			OpenAddressLocator();
		}

		private void m_btnBarriersOpen_Click(object sender, System.EventArgs e)
		{
			OpenBarriers();
		}

		private void m_btnBarriersClear_Click(object sender, System.EventArgs e)
		{
			ClearBarriers();
		}

		private void m_btnFindRoute_Click(object sender, System.EventArgs e)
		{
			FindRoute();
		}

		private void m_btnShowDirections_Click(object sender, System.EventArgs e)
		{
			ShowDirections();
		}

		private void m_btnClose_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}

		private void RoutingForm_Load(object sender, System.EventArgs e)
		{
			m_cmbDistanceUnit.SelectedIndex = 2;
		}

		private void m_btnRestrictions_Click(object sender, System.EventArgs e)
		{
			ShowRestrictions();
		}

	#endregion

	#region Public members

		// Store ArcMap application as internal member
		public void Init(IApplication application)
		{
			m_application = application;
		}

	#endregion

	#region Private Helpers

	#region Initialization helpers

		// Open Route Service file and create Router and Spatial Reference
		private void OpenRoutingService()
		{
			try
			{
				DialogResult res = m_dlgRoutingSrvc.ShowDialog(this);
				if (res == System.Windows.Forms.DialogResult.OK)
				{
					string strPath = m_dlgRoutingSrvc.FileName;

					// create router factory    
					if (m_objRouterFactory == null)
							m_objRouterFactory = new SMRouterFactoryClass();

					// if new path passed
					if ((m_objRouter == null) | (strPath != m_strRouteServicePath))
					{
						// Barriers should be created again for new Router
						ClearBarriers();

						m_strRouteServicePath = strPath;

						// create new router 
						m_objRouter = m_objRouterFactory.CreateRouter(m_strRouteServicePath);
						m_txtRoutingService.Text = m_strRouteServicePath;

						//get Router Spatial Reference
						m_objSpatialReference = CreateSpatialReference(m_objRouter.ProjectionString);

						// Init Restrictions
						m_dlgRestrictions.Init(m_objRouter);
					}
				}
			}
			catch (Exception ex)
			{
				// Clear on Error
				m_objRouter = null;
				m_objSpatialReference = null;
				m_txtRoutingService.Text = "";
				m_strRouteServicePath = "";
			}
			finally
			{
				// Check FindRoute, Barriers and Restrictions buttons state
				CheckRouteButtons();
			}
		}

		// Opens Address Locator for addresses geocoding
		private void OpenAddressLocator()
		{
			try
			{
				// Create Dialog on first call and init filter
				InitAddressLocatorDlg();

				ILocator objLocator = null;
				objLocator = null;

				// Get Locator
				IEnumGxObject gxObjects = null;
				gxObjects = null;

				if (m_dlgAddressLocator.DoModalOpen(this.Handle.ToInt32(), out gxObjects) & (gxObjects != null))
				{
					gxObjects.Reset();

					// Get first Locator
					IGxObject gxObject = null;
					gxObject = gxObjects.Next();

					if (gxObject != null)
					{
						IGxLocator gxLocator = null;
						gxLocator = gxObject as IGxLocator;
						objLocator = gxLocator.Locator;
						m_objAddressGeocoding = objLocator as IAddressGeocoding;
					}
				}

				if (m_objAddressGeocoding == null)
					m_txtAddressLocator.Text = "";
				else
					m_txtAddressLocator.Text = objLocator.Name;
			}
			catch (Exception ex)
			{
				// Clear on Error
				m_objAddressGeocoding = null;
				m_txtAddressLocator.Text = "";
			}
			finally
			{
				// Check FindRoute, Barriers and Restrictions buttons state
				CheckRouteButtons();
			}
		}

		// Adds Barriers from Dataset
		private void OpenBarriers()
		{
			System.Windows.Forms.Cursor Cursor = this.Cursor;
			try
			{
				// Create Dialog on first call and init filter
				InitBarriersDlg();

				// Get Barriers 
				IGxObject gxObject = null;

				IEnumGxObject gxObjects = null;
				gxObjects = null;

				if (m_dlgBarriers.DoModalOpen(this.Handle.ToInt32(), out gxObjects) & (gxObjects != null))
				{

					this.Cursor = Cursors.WaitCursor;

					// Init Barriers
					ClearBarriers();

					// use first object
					gxObjects.Reset();
					gxObject = gxObjects.Next();

					// Use first object
					if (gxObject != null)
					{
						// Add Barriersfrom object dataset
						IGxDataset objGxDS = null;
						objGxDS = gxObject as IGxDataset;

						AddBarriersFromDataset(objGxDS.Dataset);
					}

					// Is Barriers added to Router
					if (m_nBarriersCount == 0)
						m_txtBarriers.Text = "";
					else
						m_txtBarriers.Text = gxObject.Name;

					if (m_nBarriersIgnoredCount > 0)
						MessageBox.Show(this, m_nBarriersIgnoredCount.ToString() + " barriers cannot be added.", "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				}

			}
			catch (Exception ex)
			{
				// Clear on Error
				ClearBarriers();
			}
			finally
			{
				this.Cursor = Cursor;
			}
		}

	#endregion

	#region Finding Route helpers

		// Find route and initialize Driving Directions page
		private void FindRoute()
		{
			if (m_objRouter == null)
					return;

			// Init DD
			m_btnShowDirections.Enabled = false;
			m_dlgDirections.Init();

			System.Windows.Forms.Cursor Cursor = this.Cursor;
			try
			{
				this.Cursor = Cursors.WaitCursor;

				// set highways priority (0.0 - 100.0)    
				SMRoadPreferences objPreferences = m_objRouter.Preferences;
				objPreferences.set_Item(esriSMRoadType.esriSMRoadTypeHighways, (short)m_trackUseRoad.Value);

				// set route type (Time/Length)    
				if (m_rbtnQuickest.Checked)
					m_objRouter.NetAttributeName = "Time";
				else
					m_objRouter.NetAttributeName = "Length";

				// Set Length Units for Directions output
				SetDirectionsUnits();

				// Geocode user data and adds Start and finish
				SMStopsCollection objStopsCol = new SMStopsCollectionClass(); ;
				AddStops(objStopsCol);

				// Add restrictions
				m_dlgRestrictions.SetupRouter(m_objRouter);

				// get driving directions    
				ISMDirections objDirections = null;
				objDirections = m_objRouter.Solve(objStopsCol, null);

				// Output result, zoom to route, fill directions
				ShowResult(objDirections);

			}
			catch (Exception ex)
			{
				MessageBox.Show(this, "Cannot find route." + System.Environment.NewLine + ex.Message, "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Error);

				// Init DD
				m_btnShowDirections.Enabled = false;
				m_dlgDirections.Init();
			}
			finally
			{
				this.Cursor = Cursor;
			}

		}

		// Geocodes user data and adds Start and finish
		private void AddStops(SMStopsCollection objStopsCol)
		{
			// create and add "From" stop to stops collection    
			CreateStop(m_objRouter, m_txtStartAddress.Text, m_txtStartCity.Text, m_txtStartState.Text, m_txtStartCode.Text, objStopsCol, 0);

			// create and add "To" stop to stops collection    
			CreateStop(m_objRouter, m_txtFinishAddress.Text, m_txtFinishCity.Text, m_txtFinishState.Text, m_txtFinishCode.Text, objStopsCol, 1);
		}

		// Returns Address string
		private string GetAddressString(string strAddress, string strCity, string strState, string strCode)
		{

			string strAddress1 = strAddress;
			if (strAddress1.Length > 0)
					strAddress1 = strAddress1 + ", ";

			string strCity1 = strCity;
			if (strCity1.Length > 0)
					strCity1 = strCity1 + ", ";

			string strCode1 = strCode;
			if (strCode1.Length > 0)
					strCode1 = strCode1 + ", ";

			string strRes = strAddress1 + strCode1 + strCity1 + strState;

			if (strRes.EndsWith(", "))
					strRes = strRes.Remove(strRes.Length - 2, 2);

			return strRes;
		}

		// Geocodes address by Address, City, State, ZIP code
		private IPoint GeocodeAddress(string strAddress, string strCity, string strState, string strCode)
		{

			if (m_objAddressGeocoding == null)
				throw new Exception("Cannot geocode address.");

			// Get Address fields from textboxes
			IPropertySet objAddressProperties = new PropertySetClass();
			objAddressProperties.SetProperty("Street", strAddress);
			objAddressProperties.SetProperty("City", strCity);
			objAddressProperties.SetProperty("State", strState);
			objAddressProperties.SetProperty("ZIP", strCode);

            //// Match Address
            //IPropertySet objMatchProperties = null;
            //objMatchProperties = m_objAddressGeocoding.MatchAddress(objAddressProperties);

            //IFields objMatchFields = null;
            //objMatchFields = m_objAddressGeocoding.MatchFields;

            //if (objMatchFields.FieldCount > 0)
            //{
            //    // Use first candidate
            //    IField objMatchField = null;
            //    objMatchField = objMatchFields.get_Field(0);

            //    if (objMatchField.Type == esriFieldType.esriFieldTypeGeometry)
            //        return objMatchProperties.GetProperty(objMatchField.Name) as IPoint;
            //}

            // Match Address
            IPropertySet objMatchProperties = null;
            objMatchProperties = m_objAddressGeocoding.MatchAddress(objAddressProperties);

            IFields objMatchFields = null;
            objMatchFields = m_objAddressGeocoding.MatchFields;

            if (objMatchFields.FieldCount > 0)
            {
                // Use first candidate
                IField objGeometryField = null;

                int nFieldCount = objMatchFields.FieldCount;
                for (int nIndex = 0; nIndex < nFieldCount; nIndex++)
                {
                    IField objCurField = objMatchFields.get_Field(nIndex);
                    if (objCurField.Type == esriFieldType.esriFieldTypeGeometry)
                    {
                        objGeometryField = objCurField;
                        break;
                    }
                }

                if (objGeometryField != null)
                    return objMatchProperties.GetProperty(objGeometryField.Name) as IPoint;
                else
                    throw new Exception("Cannot obtain geometry field.");
            }

			throw new Exception("Cannot geocode address.");
		}

		// Creates Stop by Stop Point, Index and Description and adds it to Stops collection
		private void CreateStop(SMRouter objRouter, string strAddress, string strCity, string strState, string strCode, SMStopsCollection objStopsCol, int nID)
		{

			// geocode point
			IPoint objPoint = new PointClass();
			objPoint = GeocodeAddress(strAddress, strCity, strState, strCode);

			if (objPoint.IsEmpty)
					throw new Exception("Cannot geocode address.");

			// project point
			objPoint.Project(m_objSpatialReference);

			// create and initialize router point    
			SMRouterPoint objRouterPoint = null;
			objRouterPoint = new SMRouterPointClass();

			objRouterPoint.X = objPoint.X;
			objRouterPoint.Y = objPoint.Y;

			// create flag    
			ISMFlagCreator2 objFlagCreator2 = null;
			objFlagCreator2 = objRouter.FlagCreator as ISMFlagCreator2;
			if (objFlagCreator2 != null)
					objFlagCreator2.SearchTolerance = 5;

			SMFlag objFlag = null;
			objFlag = objRouter.FlagCreator.CreateFlag(objRouterPoint);

			// create and initialize stop    
			SMStop objStop = null;
			objStop = new SMStop();
			objStop.StopID = nID;
			objStop.Duration = 0;
			objStop.Flag = objFlag;
			objStop.Description = GetAddressString(strAddress, strCity, strState, strCode);

			objStopsCol.Add(objStop);
		}

		private ISpatialReference CreateSpatialReference(string strPrjString)
		{
			ISpatialReference temp_CreateSpatialReference = null;
			// create router spatial reference    
			ISpatialReferenceFactory objSpatRefFact = null;
			objSpatRefFact = new SpatialReferenceEnvironmentClass();

			// create temporary file
			string strTempPath = System.IO.Path.GetTempFileName();

			try
			{
				System.IO.StreamWriter wrtr = System.IO.File.CreateText(strTempPath);
				wrtr.Write(strPrjString);
				wrtr.Close();

				ISpatialReference objSR = null;
				objSR = objSpatRefFact.CreateESRISpatialReferenceFromPRJFile(strTempPath);

				temp_CreateSpatialReference = objSR;
			}
			finally
			{
				System.IO.File.Delete(strTempPath);
			}

			return temp_CreateSpatialReference;
		}

		// Set length unit for Direction
		private void SetDirectionsUnits()
		{
			int nIndex = m_cmbDistanceUnit.SelectedIndex;

			// Get Router Setup object
			ISMRouterSetup2 objSetup = null;
			objSetup = m_objRouter as ISMRouterSetup2;

			// get Directions unit
			esriSMDirectionsLengthUnits eUnits = 0;

			if (nIndex == 0) // Feet
				eUnits = esriSMDirectionsLengthUnits.esriSMDLUFeet;
			else if (nIndex == 1) // Yards
				eUnits = esriSMDirectionsLengthUnits.esriSMDLUYards;
			else if (nIndex == 2) // Miles
				eUnits = esriSMDirectionsLengthUnits.esriSMDLUMiles;
			else if (nIndex == 3) // Meters
				eUnits = esriSMDirectionsLengthUnits.esriSMDLUMeters;
			else if (nIndex == 4) // Kilometers
				eUnits = esriSMDirectionsLengthUnits.esriSMDLUKilometers;

			// Set Directions Unit
			objSetup.DirectionsLengthUnits = eUnits;
		}

	#endregion

	#region Resulting helpers

		// Outputs result, zoom to route, fill directions
		private void ShowResult(ISMDirections objDirections)
		{
			// Fill directions
			m_dlgDirections.Init(objDirections);
			m_btnShowDirections.Enabled = true;

			try
			{
                // Zoom to extent
				Envelope objEnv = null;
				objEnv = new Envelope();

				objEnv.PutCoords(objDirections.BoundBox.Left, objDirections.BoundBox.Bottom, objDirections.BoundBox.Right, objDirections.BoundBox.Top);
				objEnv.Expand(1.1, 1.1, true);

				// set spatial reference
				IGeometry objGeo = objEnv as IGeometry;
				objGeo.SpatialReference = m_objSpatialReference;

				ZoomToExtent(objEnv);

				// Create polyline
				CreatePolyline(objDirections);
			}
			catch (Exception ex)
			{
				MessageBox.Show(this, "Cannot show result.", "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			}
			finally
			{
				// Refresh map
				RefreshMap();
			}
		}

		// refreshes Map
		private void RefreshMap()
		{
			IMxDocument objDoc = (IMxDocument)m_application.Document; 
			IMap objMap = objDoc.FocusMap;
			IActiveView objView = objMap as IActiveView;
			objView.Refresh();
		}

		// Zooms Map to extent
		private void ZoomToExtent(Envelope objEnv)
		{
			IMxDocument objDoc = m_application.Document as IMxDocument;
			IMap objMap = objDoc.FocusMap;
			IActiveView objView = objMap as IActiveView;

			// check if projections are not equal
			IGeometry objGeo = objEnv as IGeometry;

			// project to Map projection and expand
			if (! (IsSREqual(objGeo.SpatialReference, objMap.SpatialReference)))
					((IGeometry)objEnv).Project(objMap.SpatialReference);

			// Zoom
			objView.Extent = objEnv as IEnvelope;
		}

		// Returns true if Spatial Systems is equal (without precision)
		private bool IsSREqual(ISpatialReference objSR1, ISpatialReference objSR2)
		{
			IClone objSRClone1 = objSR1 as IClone;
			return objSRClone1.IsEqual((IClone)objSR2);
		}

		// Creates Route polyline
		private void CreatePolyline(ISMDirections objDirections)
		{
			// create polyline
			IPolyline objLine = null;
			objLine = new PolylineClass();

			// get points collection
			IPointCollection objPoints = null;
			objPoints = objLine as IPointCollection;

			// Adds Directions points to polyline
			AddPointsToPolyline(objDirections, ref objPoints);

			// Project points to Map projection
			IMxDocument objDoc = m_application.Document as IMxDocument;
			IMap objMap = objDoc.FocusMap;
			objLine.Project(objMap.SpatialReference);

			// create path graphics element
			IElement objElement = null;
			objElement = new LineElementClass();

			objElement.Geometry = objLine;

			// Set line color width and style
			SetLineProperties(objElement);

            // get Graphic container
			IGraphicsContainer objCont = objMap as IGraphicsContainer;

			// Add line to map
			objCont.AddElement(objElement, 0);
		}

		// Sets line color, width and style
		private void SetLineProperties(IElement objElement)
		{
			SimpleLineSymbol objSymbol = null;
			objSymbol = new SimpleLineSymbolClass();

			// Set Symbol style and width
			objSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
			objSymbol.Width = 10;

			// Set symbol color
			RgbColor objColor = null;
			objColor = new RgbColorClass();
			objColor.Red = 0;
			objColor.Green = 255;
			objColor.Blue = 0;

			objSymbol.Color = objColor;

			// set line symbol
			ILineElement objLineElement = objElement as ILineElement;
			objLineElement.Symbol = objSymbol as ILineSymbol;
		}

		// Adds Directions points to point collection
		private void AddPointsToPolyline(ISMDirections objDirections, ref IPointCollection objPoints)
		{

			Point objPoint = new PointClass();

			// copy points from DD to line
			int nItemsCount = objDirections.Count;
			for (int i = 0; i < nItemsCount; i++)
			{
				// get shape from Direction
				ISMDirItem objItem = null;
				objItem = objDirections.get_Item(i) as ISMDirItem;

				ISMPointsCollection objShape = null;
				objShape = objItem.Shape;

                // Add point from Direction to received collection
				int nPointsCount = objShape.Count - 1;
				for (int j = 0; j <= nPointsCount; j++)
				{
					// get point from route
					SMRouterPoint objRouterPoint = objShape.get_Item(j);

                    // Optimization: Not add point if last added point has similar coords
					bool bAddPoint = false;

					if (objPoint.IsEmpty)
						bAddPoint = true;
					else if ((objPoint.X != objRouterPoint.X) & (objPoint.Y != objRouterPoint.Y))
						bAddPoint = true;

					if (bAddPoint)
					{
						// Add point if need
						objPoint.X = objRouterPoint.X;
						objPoint.Y = objRouterPoint.Y;
						objPoint.SpatialReference = m_objSpatialReference;

						object missing = System.Reflection.Missing.Value;
						objPoints.AddPoint(objPoint, ref missing, ref missing);
					}
				}
			}
		}

	#endregion

	#region Barriers helpers

		// Adds barriers from object dataset
		private void AddBarriersFromDataset(IDataset objDS)
		{
			if (objDS.Type == esriDatasetType.esriDTFeatureClass)
			{
				// It is Feature Class
				AddBarriersFromFeatureClass(objDS as IFeatureClass);

			}
			else if (objDS.Type == esriDatasetType.esriDTFeatureDataset)
			{
				// It is Feature DatasetClass

				IFeatureDataset objFeatureDS = null;
				objFeatureDS = objDS as IFeatureDataset;

				// Enum Dataset subsets
				IEnumDataset objEnumDS = null;
				objEnumDS = objFeatureDS.Subsets;

				IDataset objSubDS = null;
				objSubDS = objEnumDS.Next();
				while ( objSubDS != null)
				{
					// Add Barriers from subset Feature Class 
					if (objSubDS.Type == esriDatasetType.esriDTFeatureClass)
							AddBarriersFromFeatureClass(objSubDS as IFeatureClass);

					objSubDS = objEnumDS.Next();
				}
			}
		}

		// Adds Barriers from Feature Class 
		private void AddBarriersFromFeatureClass(IFeatureClass objFeatureClass)
		{
			// only for Point features
			if (objFeatureClass.ShapeType == esriGeometryType.esriGeometryPoint)
			{
				// create filter
				IQueryFilter objFilter = null;
				objFilter = new QueryFilterClass();

				// enum features
				IFeatureCursor objCursor = null;
				objCursor = objFeatureClass.Search(objFilter, false);

				IFeature objFeature = null;
				objFeature = objCursor.NextFeature();

				while ( objFeature != null)
				{
					// Add feature Point to Barriers List
					AddBarrier(objFeature.ShapeCopy as IPoint);

					objFeature = objCursor.NextFeature();
				}

			}
		}

		// Add Barrier
		private void AddBarrier(IPoint objPoint)
		{
			// project to Routing projection
			objPoint.Project(m_objSpatialReference);

			// add point from shape to Barriers
			ISMRouterPoint objSMPoint = null;
			objSMPoint = new SMRouterPointClass();

			objSMPoint.X = objPoint.X;
			objSMPoint.Y = objPoint.Y;

			ISMNetBarrier objBarrier = null;
			objBarrier = new SMNetBarrierClass();

			objBarrier.BarrierID = m_nBarriersCount;
			objBarrier.Point = objSMPoint as SMRouterPointClass;

			try
			{
				m_objRouter.Barriers.Add(objBarrier as SMNetBarrier);
			}
			catch (Exception ex)
			{
				m_nBarriersIgnoredCount = m_nBarriersIgnoredCount + 1;
			}

			m_nBarriersCount = m_nBarriersCount + 1;
		}

        // Clears textbox, Barriers collection in Router
		private void ClearBarriers()
		{
			m_nBarriersCount = 0;
			m_nBarriersIgnoredCount = 0;
			m_txtBarriers.Text = "";
			if (m_objRouter != null)
					m_objRouter.Barriers.Clear();
		}

	#endregion

	#region File Dialogs helpers

		// Open Directions Dialog
		private void ShowDirections()
		{
			m_dlgDirections.ShowDialog(this);
		}

		// Open Restrictions Dialog
		private void ShowRestrictions()
		{
			m_dlgRestrictions.ShowDialog(this);
		}

		// Checks FindRoute, Barriers and Restrictions buttons state
		private void CheckRouteButtons()
		{
			m_btnFindRoute.Enabled = false;
			m_btnBarriersOpen.Enabled = false;
			m_btnRestrictions.Enabled = false;

			if (m_objRouter != null)
			{
				if (m_objAddressGeocoding != null)
					m_btnFindRoute.Enabled = true;

				m_btnBarriersOpen.Enabled = true;
				m_btnRestrictions.Enabled = true;
			}
		}

		// Creates Dialog on first call and init filter
		private void InitAddressLocatorDlg()
		{
			if (m_dlgAddressLocator == null)
			{
                // Create Address Locator Dialog
				m_dlgAddressLocator = new GxDialogClass();

				IGxObjectFilter filter = null;
				filter = new GxFilterAddressLocatorsClass();

				m_dlgAddressLocator.ObjectFilter = filter;
				m_dlgAddressLocator.Title = "Add Address Locator";
			}
		}

		// Creates Dialog on first call and init filter
		private void InitBarriersDlg()
		{
			if (m_dlgBarriers == null)
			{
				// Create Barriers dialog
				m_dlgBarriers = new GxDialogClass();

				IGxObjectFilter objFilter = null;

				objFilter = new GxFilterFeatureDatasetsAndFeatureClassesClass();
				m_dlgBarriers.ObjectFilter = objFilter;

				m_dlgBarriers.Title = "Choose Barriers Layer";
			}
		}

	#endregion

	#region Imported methods
		[System.Runtime.InteropServices.DllImport("user32", EntryPoint="SetFocus", ExactSpelling=true, CharSet=System.Runtime.InteropServices.CharSet.Ansi, SetLastError=true)]
		public static extern int SetFocus(int Hwnd);
	#endregion

	#endregion

	#region Private members

		// ArcMap application
		private IApplication m_application;

		// Driving Direction dialog
		private DirectionsForm m_dlgDirections;

		// Router factory and object
		private SMRouterFactory m_objRouterFactory;
		private SMRouter m_objRouter;
		// Store Route Services path
		private string m_strRouteServicePath;
		// Spatial Reference of Router object
		private ISpatialReference m_objSpatialReference;

		// Address Locator dialog
		private GxDialog m_dlgAddressLocator;
		// Address Geocoding object
		private IAddressGeocoding m_objAddressGeocoding;

		// Barriers dialog 
		private GxDialogClass m_dlgBarriers;
		// Added Barriers count - used for current barrier ID
		private int m_nBarriersCount;
		// Number of ignored Barriers
		private int m_nBarriersIgnoredCount;

		// Restrictions dialog
		private RestrictionsForm m_dlgRestrictions;

	#endregion

	}


} //end of root namespace
[Visual Basic .NET]

RoutingForm.vb

Imports System
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Imports ESRI.ArcGIS.DataSourcesFile
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Framework
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Catalog
Imports ESRI.ArcGIS.CatalogUI
Imports ESRI.ArcGIS.Location
Imports ESRI.ArcGIS.LocationUI
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Display


Public Class RoutingForm
	Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

	Public Sub New()
		MyBase.New()

		'This call is required by the Windows Form Designer.
		InitializeComponent()

		m_dlgDirections = New DirectionsForm
		m_dlgRestrictions = New RestrictionsForm
	End Sub

#End Region

#Region "Form Buttons Events Handlers"

	' Just hides form on closing
	Private Sub RoutingForm_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
		e.Cancel = True
		Me.Hide()

		' Bug workaround.
		' ArcMap can lose focus after form closing. SetFocus prevents it.
		SetFocus(m_application.hWnd)
	End Sub

	' Bug workaround.
	' Allows Tab and Escape buttons using in form
	Private Sub RoutingForm_KeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
		If Not Me.Modal Then
			If e.KeyCode.Equals((Keys.Tab)) Then
				e.Handled = True
				Me.ProcessTabKey(Not e.Modifiers = Keys.Shift)
			ElseIf e.KeyCode.Equals((Keys.Escape)) Then
				Me.Close()
			End If
		End If
	End Sub

	' Bug workaround.
	' Allows Tab button using in form
	Protected Overrides ReadOnly Property ShowFocusCues() As Boolean
		Get
			If Me.Modal Then
				Return MyBase.ShowFocusCues
			Else
				Return True
			End If
		End Get
	End Property

	Private Sub m_btnRoutingService_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnRoutingService.Click
		OpenRoutingService()
	End Sub

	Private Sub m_btnAddressLocator_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnAddressLocator.Click
		OpenAddressLocator()
	End Sub

	Private Sub m_btnBarriersOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnBarriersOpen.Click
		OpenBarriers()
	End Sub

	Private Sub m_btnBarriersClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnBarriersClear.Click
		ClearBarriers()
	End Sub

	Private Sub m_btnFindRoute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnFindRoute.Click
		FindRoute()
	End Sub

	Private Sub m_btnShowDirections_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnShowDirections.Click
		ShowDirections()
	End Sub

	Private Sub m_btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnClose.Click
		Me.Close()
	End Sub

	Private Sub RoutingForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
		m_cmbDistanceUnit.SelectedIndex = 2
	End Sub

	Private Sub m_btnRestrictions_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles m_btnRestrictions.Click
		ShowRestrictions()
	End Sub

#End Region

#Region "Public members"

	' Store ArcMap application as internal member
	Public Sub Init(ByVal application As IApplication)
		m_application = application
	End Sub

#End Region

#Region "Private Helpers"

#Region "Initialization helpers"

	' Open Route Service file and create Router and Spatial Reference
	Private Sub OpenRoutingService()
		Try
			Dim res As DialogResult = m_dlgRoutingSrvc.ShowDialog(Me)
			If res = System.Windows.Forms.DialogResult.OK Then
				Dim strPath As String = m_dlgRoutingSrvc.FileName

				' create router factory	
				If m_objRouterFactory Is Nothing Then _
				 m_objRouterFactory = New SMRouterFactoryClass

				' if new path passed
				If (m_objRouter Is Nothing) Or (strPath <> m_strRouteServicePath) Then
					' Barriers should be created again for new Router
					ClearBarriers()

					m_strRouteServicePath = strPath

					' create new router 
					m_objRouter = m_objRouterFactory.CreateRouter(m_strRouteServicePath)
					m_txtRoutingService.Text = m_strRouteServicePath

					'get Router Spatial Reference
					m_objSpatialReference = CreateSpatialReference(m_objRouter.ProjectionString)

					' Init Restrictions
					m_dlgRestrictions.Init(m_objRouter)
				End If
			End If
		Catch ex As Exception
			' Clear on Error
			m_objRouter = Nothing
			m_objSpatialReference = Nothing
			m_txtRoutingService.Text = ""
			m_strRouteServicePath = ""
		Finally
			' Check FindRoute, Barriers and Restrictions buttons state
			CheckRouteButtons()
		End Try
	End Sub

	' Opens Address Locator for addresses geocoding
	Private Sub OpenAddressLocator()
		Try
			' Create Dialog on first call and init filter
			InitAddressLocatorDlg()

			Dim objLocator As ILocator
			objLocator = Nothing

			' Get Locator
			Dim gxObjects As IEnumGxObject
			gxObjects = Nothing

			If m_dlgAddressLocator.DoModalOpen(Me.Handle.ToInt32, gxObjects) And (Not gxObjects Is Nothing) Then
				gxObjects.Reset()

				' Get first Locator
				Dim gxObject As IGxObject
				gxObject = gxObjects.Next()

				If Not gxObject Is Nothing Then
					Dim gxLocator As IGxLocator
					gxLocator = gxObject
					objLocator = gxLocator.Locator
					m_objAddressGeocoding = objLocator
				End If
			End If

			If m_objAddressGeocoding Is Nothing Then
				m_txtAddressLocator.Text = ""
			Else
				m_txtAddressLocator.Text = objLocator.Name
			End If
		Catch ex As Exception
			' Clear on Error
			m_objAddressGeocoding = Nothing
			m_txtAddressLocator.Text = ""
		Finally
			' Check FindRoute, Barriers and Restrictions buttons state
			CheckRouteButtons()
		End Try
	End Sub

	' Adds Barriers from Dataset
	Private Sub OpenBarriers()
		Dim Cursor As System.Windows.Forms.Cursor = Me.Cursor
		Try
			' Create Dialog on first call and init filter
			InitBarriersDlg()

			' Get Barriers 
			Dim gxObject As IGxObject

			Dim gxObjects As IEnumGxObject
			gxObjects = Nothing

			If m_dlgBarriers.DoModalOpen(Me.Handle.ToInt32, gxObjects) And (Not gxObjects Is Nothing) Then

				Me.Cursor = Cursors.WaitCursor

				' Init Barriers
				ClearBarriers()

				' use first object
				gxObjects.Reset()
				gxObject = gxObjects.Next()

				' Use first object
				If Not gxObject Is Nothing Then
					' Add Barriersfrom object dataset
					Dim objGxDS As IGxDataset
					objGxDS = gxObject

					AddBarriersFromDataset(objGxDS.Dataset)
				End If

				' Is Barriers added to Router
				If m_nBarriersCount = 0 Then
					m_txtBarriers.Text = ""
				Else
					m_txtBarriers.Text = gxObject.Name
				End If

				If m_nBarriersIgnoredCount > 0 Then
					MessageBox.Show(Me, m_nBarriersIgnoredCount.ToString + " barriers cannot be added.", _
					 "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
				End If
			End If

		Catch ex As Exception
			' Clear on Error
			ClearBarriers()
		Finally
			Me.Cursor = Cursor
		End Try
	End Sub

#End Region

#Region "Finding Route helpers"

	' Find route and initialize Driving Directions page
	Private Sub FindRoute()
		If m_objRouter Is Nothing Then _
			Exit Sub

		' Init DD
		m_btnShowDirections.Enabled = False
		m_dlgDirections.Init()

		Dim Cursor As System.Windows.Forms.Cursor = Me.Cursor
		Try
			Me.Cursor = Cursors.WaitCursor

			' set highways priority (0.0 - 100.0)	
			Dim objPreferences As SMRoadPreferences
			objPreferences = m_objRouter.Preferences
			objPreferences.Item(esriSMRoadType.esriSMRoadTypeHighways) = CShort(m_trackUseRoad.Value)

			' set route type (Time/Length)	
			If m_rbtnQuickest.Checked Then
				m_objRouter.NetAttributeName = "Time"
			Else
				m_objRouter.NetAttributeName = "Length"
			End If

			' Set Length Units for Directions output
			SetDirectionsUnits()

			' Geocode user data and adds Start and finish
			Dim objStopsCol As SMStopsCollection
			objStopsCol = New SMStopsCollectionClass
			AddStops(objStopsCol)

			' Add restrictions
			m_dlgRestrictions.SetupRouter(m_objRouter)

			' get driving directions	
			Dim objDirections As ISMDirections
			objDirections = m_objRouter.Solve(objStopsCol, Nothing)

			' Output result, zoom to route, fill directions
			ShowResult(objDirections)

		Catch ex As Exception
			MessageBox.Show(Me, "Cannot find route." + vbCrLf + ex.Message, _
			 "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Error)

			' Init DD
			m_btnShowDirections.Enabled = False
			m_dlgDirections.Init()
		Finally
			Me.Cursor = Cursor
		End Try

	End Sub

	' Geocodes user data and adds Start and finish
	Private Sub AddStops(ByVal objStopsCol As SMStopsCollection)
		' create and add "From" stop to stops collection	
		CreateStop(m_objRouter, _
		 m_txtStartAddress.Text, m_txtStartCity.Text, _
		 m_txtStartState.Text, m_txtStartCode.Text, _
		 objStopsCol, 0)

		' create and add "To" stop to stops collection	
		CreateStop(m_objRouter, _
		 m_txtFinishAddress.Text, m_txtFinishCity.Text, _
		 m_txtFinishState.Text, m_txtFinishCode.Text, _
		 objStopsCol, 1)
	End Sub

	' Returns Address string
	Private Function GetAddressString(ByVal strAddress As String, ByVal strCity As String, _
	  ByVal strState As String, ByVal strCode As String) As String

		Dim strAddress1 As String = strAddress
		If strAddress1.Length > 0 Then _
		 strAddress1 = strAddress1 + ", "

		Dim strCity1 As String = strCity
		If strCity1.Length > 0 Then _
		 strCity1 = strCity1 + ", "

		Dim strCode1 As String = strCode
		If strCode1.Length > 0 Then _
		 strCode1 = strCode1 + ", "

		Dim strRes As String = strAddress1 + strCode1 + strCity1 + strState

		If strRes.EndsWith(", ") Then _
		 strRes = strRes.Remove(strRes.Length - 2, 2)

		Return strRes
	End Function

	' Geocodes address by Address, City, State, ZIP code
    Private Function GeocodeAddress(ByVal strAddress As String, ByVal strCity As String, _
      ByVal strState As String, ByVal strCode As String) As IPoint

        If m_objAddressGeocoding Is Nothing Then
            Throw New Exception("Cannot geocode address.")
        End If

        ' Get Address fields from textboxes
        Dim objAddressProperties As IPropertySet
        objAddressProperties = New PropertySetClass
        With objAddressProperties
            .SetProperty("Street", strAddress)
            .SetProperty("City", strCity)
            .SetProperty("State", strState)
            .SetProperty("ZIP", strCode)
        End With

        ' Match Address
        Dim objMatchProperties As IPropertySet
        objMatchProperties = m_objAddressGeocoding.MatchAddress(objAddressProperties)

        Dim objMatchFields As IFields
        objMatchFields = m_objAddressGeocoding.MatchFields

        If objMatchFields.FieldCount > 0 Then
            ' Use first candidate
            Dim objGeometryField As IField
            Dim nFieldCount As Integer = objMatchFields.FieldCount
            Dim nIndex As Integer
            'objMatchField = objMatchFields.Field(0)
            For nIndex = 0 To (nFieldCount - 1)
                Dim objCurField As IField = objMatchFields.Field(nIndex)
                If objCurField.Type = esriFieldType.esriFieldTypeGeometry Then
                    objGeometryField = objCurField
                End If
            Next

            If Not objGeometryField Is Nothing Then
                Return objMatchProperties.GetProperty(objGeometryField.Name)
            Else
                Throw New Exception("Cannot obtain geometry field.")
            End If
        End If

        Throw New Exception("Cannot geocode address.")
    End Function

    ' Creates Stop by Stop Point, Index and Description and adds it to Stops collection
    Private Sub CreateStop(ByVal objRouter As SMRouter, _
      ByVal strAddress As String, ByVal strCity As String, _
      ByVal strState As String, ByVal strCode As String, _
      ByVal objStopsCol As SMStopsCollection, _
      ByVal nID As Integer)

        ' geocode point
        Dim objPoint As Point
        objPoint = GeocodeAddress(strAddress, strCity, strState, strCode)

        If objPoint.IsEmpty Then _
         Throw New Exception("Cannot geocode address.")

        ' project point
        objPoint.Project(m_objSpatialReference)

        ' create and initialize router point	
        Dim objRouterPoint As SMRouterPoint
        objRouterPoint = New SMRouterPointClass

        objRouterPoint.X = objPoint.X
        objRouterPoint.Y = objPoint.Y

        ' create flag	
        Dim objFlagCreator2 As ISMFlagCreator2
        objFlagCreator2 = objRouter.FlagCreator
        If Not objFlagCreator2 Is Nothing Then _
         objFlagCreator2.SearchTolerance = 5

        Dim objFlag As SMFlag
        objFlag = objRouter.FlagCreator.CreateFlag(objRouterPoint)

        ' create and initialize stop	
        Dim objStop As SMStop
        objStop = New SMStopClass
        objStop.StopID = nID
        objStop.Duration = 0
        objStop.Flag = objFlag
        objStop.Description = GetAddressString(strAddress, strCity, strState, strCode)

        objStopsCol.Add(objStop)
    End Sub

	Private Function CreateSpatialReference(ByVal strPrjString As String) As ISpatialReference
		' create router spatial reference	
		Dim objSpatRefFact As ISpatialReferenceFactory
		objSpatRefFact = New SpatialReferenceEnvironmentClass

		' create temporary file
		Dim strTempPath As String = System.IO.Path.GetTempFileName()

		Try
			Dim wrtr As System.IO.StreamWriter = System.IO.File.CreateText(strTempPath)
			wrtr.Write(strPrjString)
			wrtr.Close()

			Dim objSR As ISpatialReference
			objSR = objSpatRefFact.CreateESRISpatialReferenceFromPRJFile(strTempPath)

			CreateSpatialReference = objSR
		Finally
			System.IO.File.Delete(strTempPath)
		End Try

	End Function

	' Set length unit for Direction
	Private Sub SetDirectionsUnits()
		Dim nIndex As Integer = m_cmbDistanceUnit.SelectedIndex

		' Get Router Setup object
        Dim objSetup As ISMRouterSetup2
		objSetup = m_objRouter

		' get Directions unit
		Dim eUnits As esriSMDirectionsLengthUnits

		If nIndex = 0 Then ' Feet
			eUnits = esriSMDirectionsLengthUnits.esriSMDLUFeet
		ElseIf nIndex = 1 Then ' Yards
			eUnits = esriSMDirectionsLengthUnits.esriSMDLUYards
		ElseIf nIndex = 2 Then ' Miles
			eUnits = esriSMDirectionsLengthUnits.esriSMDLUMiles
		ElseIf nIndex = 3 Then ' Meters
			eUnits = esriSMDirectionsLengthUnits.esriSMDLUMeters
		ElseIf nIndex = 4 Then ' Kilometers
			eUnits = esriSMDirectionsLengthUnits.esriSMDLUKilometers
		End If

		' Set Directions Unit
		objSetup.DirectionsLengthUnits = eUnits
	End Sub

#End Region

#Region "Resulting helpers"

	' Outputs result, zoom to route, fill directions
	Private Sub ShowResult(ByVal objDirections As ISMDirections)
		' Fill directions
		m_dlgDirections.Init(objDirections)
		m_btnShowDirections.Enabled = True

		Try
            ' Zoom to extent
			Dim objEnv As Envelope
			objEnv = New EnvelopeClass

			objEnv.PutCoords(objDirections.BoundBox.Left, objDirections.BoundBox.Bottom, _
			 objDirections.BoundBox.Right, objDirections.BoundBox.Top)
			objEnv.Expand(1.1, 1.1, True)

			' set spatial reference
			Dim objGeo As IGeometry = objEnv
			objGeo.SpatialReference = m_objSpatialReference

			ZoomToExtent(objEnv)

			' Create polyline
			CreatePolyline(objDirections)
		Catch ex As Exception
			MessageBox.Show(Me, "Cannot show result.", _
			 "Routing Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
		Finally
			' Refresh map
			RefreshMap()
		End Try
	End Sub

	' refreshes Map
	Private Sub RefreshMap()
		Dim objDoc As IMxDocument
		objDoc = m_application.Document

		Dim objMap As Map
		objMap = objDoc.FocusMap

		Dim objView As IActiveView
		objView = objMap

		objView.Refresh()
	End Sub

	' Zooms Map to extent
	Private Sub ZoomToExtent(ByVal objEnv As Envelope)
		Dim objDoc As IMxDocument
		objDoc = m_application.Document

		Dim objMap As Map
		objMap = objDoc.FocusMap

		Dim objView As IActiveView
		objView = objMap

		' check if projections are not equal
		Dim objGeo As IGeometry = objEnv

		' project to Map projection and expand
		If Not IsSREqual(objGeo.SpatialReference, objMap.SpatialReference) Then _
		 objEnv.Project(objMap.SpatialReference)

		' Zoom
		objView.Extent = objEnv
	End Sub

	' Returns true if Spatial Systems is equal (without precision)
	Private Function IsSREqual(ByVal objSR1 As ISpatialReference, _
	  ByVal objSR2 As ISpatialReference) As Boolean
		Dim objSRClone1 As IClone = objSR1
		IsSREqual = objSRClone1.IsEqual(objSR2)
	End Function

	' Creates Route polyline
	Private Sub CreatePolyline(ByVal objDirections As ISMDirections)
		' create polyline
		Dim objLine As IPolyline
		objLine = New PolylineClass

		' get points collection
		Dim objPoints As IPointCollection
		objPoints = objLine

		' Adds Directions points to polyline
		AddPointsToPolyline(objDirections, objPoints)

		' Project points to Map projection
		Dim objDoc As IMxDocument
		objDoc = m_application.Document
		Dim objMap As Map = objDoc.FocusMap
		objLine.Project(objMap.SpatialReference)

		' create path graphics element
		Dim objElement As IElement
		objElement = New LineElementClass

		objElement.Geometry = objLine

		' Set line color width and style
		SetLineProperties(objElement)

        ' get Graphic container
		Dim objCont As IGraphicsContainer = objMap

		' Add line to map
		objCont.AddElement(objElement, 0)
	End Sub

	' Sets line color, width and style
	Private Sub SetLineProperties(ByVal objElement As IElement)
		Dim objSymbol As SimpleLineSymbol
		objSymbol = New SimpleLineSymbolClass

		' Set Symbol style and width
		objSymbol.Style = esriSimpleLineStyle.esriSLSSolid
		objSymbol.Width = 10

		' Set symbol color
		Dim objColor As RgbColor
		objColor = New RgbColorClass
		objColor.Red = 0
		objColor.Green = 255
		objColor.Blue = 0

		objSymbol.Color = objColor

		' set line symbol
		Dim objLineElement As ILineElement = objElement
		objLineElement.Symbol = objSymbol
	End Sub

	' Adds Directions points to point collection
	Private Sub AddPointsToPolyline(ByVal objDirections As ISMDirections, _
	  ByRef objPoints As IPointCollection)

		Dim objPoint As Point
		objPoint = New PointClass

		' copy points from DD to line
		Dim nItemsCount As Integer = objDirections.Count
		For i As Integer = 0 To nItemsCount - 1

			' get shape from Direction
			Dim objItem As ISMDirItem
			objItem = objDirections.Item(i)

			Dim objShape As ISMPointsCollection
			objShape = objItem.Shape

            ' Add point from Direction to received collection
			Dim nPointsCount As Integer = objShape.Count - 1
			For j As Integer = 0 To nPointsCount

				' get point from route
				Dim objRouterPoint As SMRouterPoint = objShape.Item(j)

                ' Optimization: Not add point if last added point has similar coords
				Dim bAddPoint As Boolean = False

				If objPoint.IsEmpty Then
					bAddPoint = True
				ElseIf (objPoint.X <> objRouterPoint.X) And (objPoint.Y <> objRouterPoint.Y) Then
					bAddPoint = True
				End If

				If bAddPoint Then
					' Add point if need
					objPoint.X = objRouterPoint.X
					objPoint.Y = objRouterPoint.Y
					objPoint.SpatialReference = m_objSpatialReference

					objPoints.AddPoint(objPoint)
				End If
			Next
		Next
	End Sub

#End Region

#Region "Barriers helpers"

	' Adds barriers from object dataset
	Private Sub AddBarriersFromDataset(ByVal objDS As IDataset)
		If objDS.Type = esriDatasetType.esriDTFeatureClass Then
			' It is Feature Class
			AddBarriersFromFeatureClass(objDS)

		ElseIf objDS.Type = esriDatasetType.esriDTFeatureDataset Then
			' It is Feature DatasetClass

			Dim objFeatureDS As IFeatureDataset
			objFeatureDS = objDS

			' Enum Dataset subsets
			Dim objEnumDS As IEnumDataset
			objEnumDS = objFeatureDS.Subsets

			Dim objSubDS As IDataset
			objSubDS = objEnumDS.Next
			Do Until objSubDS Is Nothing
				' Add Barriers from subset Feature Class 
				If objSubDS.Type = esriDatasetType.esriDTFeatureClass Then _
				 AddBarriersFromFeatureClass(objSubDS)

				objSubDS = objEnumDS.Next
			Loop
		End If
	End Sub

	' Adds Barriers from Feature Class 
	Private Sub AddBarriersFromFeatureClass(ByVal objFeatureClass As IFeatureClass)
		' only for Point features
		If objFeatureClass.ShapeType = esriGeometryType.esriGeometryPoint Then
			' create filter
			Dim objFilter As IQueryFilter
			objFilter = New QueryFilterClass

			' enum features
			Dim objCursor As IFeatureCursor
			objCursor = objFeatureClass.Search(objFilter, False)

			Dim objFeature As IFeature
			objFeature = objCursor.NextFeature

			Do Until objFeature Is Nothing
				' Add feature Point to Barriers List
				AddBarrier(objFeature.ShapeCopy)

				objFeature = objCursor.NextFeature
			Loop

		End If
	End Sub

	' Add Barrier
	Private Sub AddBarrier(ByVal objPoint As IPoint)
		' project to Routing projection
		objPoint.Project(m_objSpatialReference)

		' add point from shape to Barriers
		Dim objSMPoint As ISMRouterPoint
		objSMPoint = New SMRouterPointClass

		objSMPoint.X = objPoint.X
		objSMPoint.Y = objPoint.Y

		Dim objBarrier As ISMNetBarrier
		objBarrier = New SMNetBarrierClass

		objBarrier.BarrierID = m_nBarriersCount
		objBarrier.Point = objSMPoint

		Try
			m_objRouter.Barriers.Add(objBarrier)
		Catch ex As Exception
			m_nBarriersIgnoredCount = m_nBarriersIgnoredCount + 1
		End Try

		m_nBarriersCount = m_nBarriersCount + 1
	End Sub

    ' Clears textbox, Barriers collection in Router
	Private Sub ClearBarriers()
		m_nBarriersCount = 0
		m_nBarriersIgnoredCount = 0
		m_txtBarriers.Text = ""
		If Not m_objRouter Is Nothing Then _
		 m_objRouter.Barriers.Clear()
	End Sub

#End Region

#Region "File Dialogs helpers"

	' Open Directions Dialog
	Private Sub ShowDirections()
		m_dlgDirections.ShowDialog(Me)
	End Sub

	' Open Restrictions Dialog
	Private Sub ShowRestrictions()
		m_dlgRestrictions.ShowDialog(Me)
	End Sub

	' Checks FindRoute, Barriers and Restrictions buttons state
	Private Sub CheckRouteButtons()
		m_btnFindRoute.Enabled = False
		m_btnBarriersOpen.Enabled = False
		m_btnRestrictions.Enabled = False

		If Not m_objRouter Is Nothing Then
			If Not m_objAddressGeocoding Is Nothing Then
				m_btnFindRoute.Enabled = True
			End If

			m_btnBarriersOpen.Enabled = True
			m_btnRestrictions.Enabled = True
		End If
	End Sub

	' Creates Dialog on first call and init filter
	Private Sub InitAddressLocatorDlg()
		If m_dlgAddressLocator Is Nothing Then
            ' Create Address Locator Dialog
			m_dlgAddressLocator = New GxDialogClass

			Dim filter As IGxObjectFilter
			filter = New GxFilterAddressLocatorsClass

			m_dlgAddressLocator.ObjectFilter = filter
			m_dlgAddressLocator.Title = "Add Address Locator"
		End If
	End Sub

	' Creates Dialog on first call and init filter
	Private Sub InitBarriersDlg()
		If m_dlgBarriers Is Nothing Then
			' Create Barriers dialog
			m_dlgBarriers = New GxDialogClass

			Dim objFilter As IGxObjectFilter

			objFilter = New GxFilterFeatureDatasetsAndFeatureClassesClass
			m_dlgBarriers.ObjectFilter = objFilter

			m_dlgBarriers.Title = "Choose Barriers Layer"
		End If
	End Sub

#End Region

#Region "Imported methods"
	Public Declare Ansi Function SetFocus Lib "user32" (ByVal Hwnd As Integer) As Integer
#End Region

#End Region

#Region "Private members"

	' ArcMap application
	Private m_application As IApplication

	' Driving Direction dialog
	Private m_dlgDirections As DirectionsForm

	' Router factory and object
	Private m_objRouterFactory As SMRouterFactory
	Private m_objRouter As SMRouter
	' Store Route Services path
	Private m_strRouteServicePath As String
	' Spatial Reference of Router object
	Private m_objSpatialReference As ISpatialReference

	' Address Locator dialog
	Private m_dlgAddressLocator As GxDialog
	' Address Geocoding object
	Private m_objAddressGeocoding As IAddressGeocoding

	' Barriers dialog 
	Private m_dlgBarriers As GxDialogClass
	' Added Barriers count - used for current barrier ID
	Private m_nBarriersCount As Integer
	' Number of ignored Barriers
	Private m_nBarriersIgnoredCount As Integer

	' Restrictions dialog
	Private m_dlgRestrictions As RestrictionsForm

#End Region

End Class