ArcObjects Library Reference  

frmServiceAreaSolver

About the Service area solver Sample

[C#]

frmServiceAreaSolver.cs

using System;
using System.Windows.Forms;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.NetworkAnalyst;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;

namespace ServiceAreaSolver
{
	public partial class frmServiceAreaSolver : Form
	{
		private INAContext m_naContext;

		#region Main Form Constructor and Setup

		public frmServiceAreaSolver()
		{
			InitializeComponent();

			txtCutOff.Text = "5";
			lbOutput.Items.Clear();
			cbCostAttribute.Items.Clear();
			ckbShowLines.Checked = false;
			ckbUseRestriction.Checked = false;
			axMapControl.ClearLayers();

			txtWorkspacePath.Text = Application.StartupPath + @"\..\..\..\..\..\Data\SanFrancisco\SanFrancisco.gdb";
			txtNetworkDataset.Text = "Streets_ND";
			txtFeatureDataset.Text = "Transportation";
			txtInputFacilities.Text = "Hospitals";
			gbServiceAreaSolver.Enabled = false;
		}

		#endregion

		#region Button Clicks

		private void btnSolve_Click(object sender, EventArgs e)
		{
			this.Cursor = Cursors.WaitCursor;
			lbOutput.Items.Clear();

			ConfigureSolverSettings();

			try
			{
				IGPMessages gpMessages = new GPMessagesClass();
				if (m_naContext.Solver.Solve(m_naContext, gpMessages, null))
					LoadListboxAfterPartialSolve(gpMessages);
				else
					LoadListboxAfterSuccessfulSolve();
			}
			catch (Exception ex)
			{
				lbOutput.Items.Add("Solve Failed: " + ex.Message);
			}

			UpdateMapDisplayAfterSolve();

			this.Cursor = Cursors.Default;
		}

		private void btnLoadMap_Click(object sender, EventArgs e)
		{
			this.Cursor = Cursors.WaitCursor;

			gbServiceAreaSolver.Enabled = false;
			lbOutput.Items.Clear();

			IWorkspace workspace = OpenWorkspace(txtWorkspacePath.Text);
			if (workspace == null)
			{
				this.Cursor = Cursors.Default;
				return;
			}

			INetworkDataset networkDataset = OpenNetworkDataset(workspace, txtFeatureDataset.Text, txtNetworkDataset.Text);
			IFeatureWorkspace featureWorkspace = workspace as IFeatureWorkspace;
			CreateContextAndSolver(networkDataset);

			if (m_naContext == null)
			{
				this.Cursor = Cursors.Default;
				return;
			}

			LoadCostAttributes(networkDataset);

			if (!LoadLocations(featureWorkspace))
			{
				this.Cursor = Cursors.Default;
				return;
			}

			AddNetworkDatasetLayerToMap(networkDataset);
			AddNetworkAnalysisLayerToMap();

			// work around a transparency issue
			IGeoDataset geoDataset = networkDataset as IGeoDataset;
			axMapControl.Extent = axMapControl.FullExtent;
			axMapControl.Extent = geoDataset.Extent;

			if (m_naContext != null) gbServiceAreaSolver.Enabled = true;

			this.Cursor = Cursors.Default;
		}

		#endregion

		#region Set up Context and Solver

		//*********************************************************************************
		// Geodatabase functions
		// ********************************************************************************
		public IWorkspace OpenWorkspace(string strGDBName)
		{
			// As Workspace Factories are Singleton objects, they must be instantiated with the Activator
			var workspaceFactory = System.Activator.CreateInstance(System.Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory")) as ESRI.ArcGIS.Geodatabase.IWorkspaceFactory;

			if (!System.IO.Directory.Exists(txtWorkspacePath.Text))
			{
				MessageBox.Show("The workspace: " + txtWorkspacePath.Text + " does not exist", "Workspace Error");
				return null;
			}

			IWorkspace workspace = null;
			try
			{
				workspace = workspaceFactory.OpenFromFile(txtWorkspacePath.Text, 0);
			}
			catch (Exception ex)
			{
				MessageBox.Show("Opening workspace failed: " + ex.Message, "Workspace Error");
			}

			return workspace;
		}

		public INetworkDataset OpenNetworkDataset(IWorkspace workspace, string featureDatasetName, string strNDSName)
		{
			// Obtain the dataset container from the workspace
			var featureWorkspace = workspace as IFeatureWorkspace;
			ESRI.ArcGIS.Geodatabase.IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName);
			var featureDatasetExtensionContainer = featureDataset as ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer;
			ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtension featureDatasetExtension = featureDatasetExtensionContainer.FindExtension(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset);
			var datasetContainer3 = featureDatasetExtension as ESRI.ArcGIS.Geodatabase.IDatasetContainer3;

			// Use the container to open the network dataset.
			ESRI.ArcGIS.Geodatabase.IDataset dataset = datasetContainer3.get_DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, strNDSName);
			return dataset as ESRI.ArcGIS.Geodatabase.INetworkDataset;
		}

		private void CreateContextAndSolver(INetworkDataset networkDataset)
		{
			if (networkDataset == null) return;

			IDatasetComponent datasetComponent = networkDataset as IDatasetComponent;
			IDENetworkDataset deNetworkDataset = datasetComponent.DataElement as IDENetworkDataset;

			INASolver naSolver = new NAServiceAreaSolverClass();
			m_naContext = naSolver.CreateContext(deNetworkDataset, "ServiceArea");
			INAContextEdit naContextEdit = m_naContext as INAContextEdit;
			naContextEdit.Bind(networkDataset, new GPMessagesClass());
		}

		#endregion

		#region Load Form Controls

		private void LoadCostAttributes(INetworkDataset networkDataset)
		{
			cbCostAttribute.Items.Clear();

			int attrCount = networkDataset.AttributeCount;
			for (int attrIndex = 0; attrIndex < attrCount; attrIndex++)
			{
				INetworkAttribute networkAttribute = networkDataset.get_Attribute(attrIndex);
				if (networkAttribute.UsageType == esriNetworkAttributeUsageType.esriNAUTCost)
					cbCostAttribute.Items.Add(networkAttribute.Name);
			}

			if (cbCostAttribute.Items.Count > 0)
				cbCostAttribute.SelectedIndex = 0;
		}

		private bool LoadLocations(IFeatureWorkspace featureWorkspace)
		{
			IFeatureClass inputFeatureClass = null;
			try
			{
				inputFeatureClass = featureWorkspace.OpenFeatureClass(txtInputFacilities.Text);
			}
			catch (Exception)
			{
				MessageBox.Show("Specified input feature class does not exist");
				return false;
			}

			INamedSet classes = m_naContext.NAClasses;
			INAClass naClass = classes.get_ItemByName("Facilities") as INAClass;

			// delete existing locations, except barriers
			naClass.DeleteAllRows();

			// Create a NAClassLoader and set the snap tolerance (meters unit)
			INAClassLoader naClassLoader = new NAClassLoaderClass();
			naClassLoader.Locator = m_naContext.Locator;
			naClassLoader.Locator.SnapTolerance = 100;
			naClassLoader.NAClass = naClass;

			// Create field map to automatically map fields from input class to NAClass
			INAClassFieldMap naClassFieldMap = new NAClassFieldMapClass();
			naClassFieldMap.CreateMapping(naClass.ClassDefinition, inputFeatureClass.Fields);
			naClassLoader.FieldMap = naClassFieldMap;

			// Avoid loading network locations onto non-traversable portions of elements
			INALocator3 locator = m_naContext.Locator as INALocator3;
			locator.ExcludeRestrictedElements = true;
			locator.CacheRestrictedElements(m_naContext);

			// load network locations
			int rowsIn = 0;
			int rowsLocated = 0;
			naClassLoader.Load(inputFeatureClass.Search(null, true) as ICursor, null, ref rowsIn, ref rowsLocated);

			if (rowsLocated <= 0)
			{
				MessageBox.Show("Facilities were not loaded from input feature class");
				return false;
			}

			// Message all of the network analysis agents that the analysis context has changed
			INAContextEdit naContextEdit = m_naContext as INAContextEdit;
			naContextEdit.ContextChanged();

			return true;
		}

		private void AddNetworkAnalysisLayerToMap()
		{
			ILayer layer = m_naContext.Solver.CreateLayer(m_naContext) as ILayer;
			layer.Name = m_naContext.Solver.DisplayName;
			axMapControl.AddLayer(layer);
		}

		private void AddNetworkDatasetLayerToMap(INetworkDataset networkDataset)
		{
			INetworkLayer networkLayer = new NetworkLayerClass();
			networkLayer.NetworkDataset = networkDataset;
			ILayer layer = networkLayer as ILayer;
			layer.Name = "Network Dataset";
			axMapControl.AddLayer(layer);
		}

		#endregion

		#region Solver Settings

		private void ConfigureSolverSettings()
		{
			ConfigureSettingsSpecificToServiceAreaSolver();

			ConfigureGenericSolverSettings();

			UpdateContextAfterChangingSettings();
		}

		private void ConfigureSettingsSpecificToServiceAreaSolver()
		{
			INAServiceAreaSolver naSASolver = m_naContext.Solver as INAServiceAreaSolver;

			naSASolver.DefaultBreaks = ParseBreaks(txtCutOff.Text);

			naSASolver.MergeSimilarPolygonRanges = false;
			naSASolver.OutputPolygons = esriNAOutputPolygonType.esriNAOutputPolygonSimplified;
			naSASolver.OverlapLines = true;
			naSASolver.SplitLinesAtBreaks = false;
			naSASolver.TravelDirection = esriNATravelDirection.esriNATravelDirectionFromFacility;

			if (ckbShowLines.Checked)
				naSASolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShape;
			else
				naSASolver.OutputLines = esriNAOutputLineType.esriNAOutputLineNone;
		}

		private void ConfigureGenericSolverSettings()
		{
			INASolverSettings naSolverSettings = m_naContext.Solver as INASolverSettings;
			naSolverSettings.ImpedanceAttributeName = cbCostAttribute.Text;

			// set the oneway restriction, if necessary
			IStringArray restrictions = naSolverSettings.RestrictionAttributeNames;
			restrictions.RemoveAll();
			if (ckbUseRestriction.Checked)
				restrictions.Add("Oneway");
			naSolverSettings.RestrictionAttributeNames = restrictions;
			//naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
		}

		private void UpdateContextAfterChangingSettings()
		{
			IDatasetComponent datasetComponent = m_naContext.NetworkDataset as IDatasetComponent;
			IDENetworkDataset deNetworkDataset = datasetComponent.DataElement as IDENetworkDataset;
			m_naContext.Solver.UpdateContext(m_naContext, deNetworkDataset, new GPMessagesClass());
		}

		private IDoubleArray ParseBreaks(string p)
		{
			String[] breaks = p.Split(' ');
			IDoubleArray pBrks = new DoubleArrayClass();
			int firstIndex = breaks.GetLowerBound(0);
			int lastIndex = breaks.GetUpperBound(0);
			for (int splitIndex = firstIndex; splitIndex <= lastIndex; splitIndex++)
			{
				try
				{
					pBrks.Add(Convert.ToDouble(breaks[splitIndex]));
				}
				catch (FormatException)
				{
					MessageBox.Show("Breaks are not properly formatted.  Use only digits separated by spaces");
					pBrks.RemoveAll();
					return pBrks;
				}
			}

			return pBrks;
		}

		#endregion

		#region Post-Solve

		private void LoadListboxAfterPartialSolve(IGPMessages gpMessages)
		{
			lbOutput.Items.Add("Partial Solve Generated.");
			for (int msgIndex = 0; msgIndex < gpMessages.Messages.Count; msgIndex++)
			{
				string errorText = "";
				switch (gpMessages.GetMessage(msgIndex).Type)
				{
					case esriGPMessageType.esriGPMessageTypeError:
						errorText = "Error " + gpMessages.GetMessage(msgIndex).ErrorCode.ToString() + " " + gpMessages.GetMessage(msgIndex).Description;
						break;
					case esriGPMessageType.esriGPMessageTypeWarning:
						errorText = "Warning " + gpMessages.GetMessage(msgIndex).ErrorCode.ToString() + " " + gpMessages.GetMessage(msgIndex).Description;
						break;
					default:
						errorText = "Information " + gpMessages.GetMessage(msgIndex).Description;
						break;
				}
				lbOutput.Items.Add(errorText);
			}
		}

		private void LoadListboxAfterSuccessfulSolve()
		{
			ITable table = m_naContext.NAClasses.get_ItemByName("SAPolygons") as ITable;
			if (table.RowCount(null) > 0)
			{
				IGPMessage gpMessage = new GPMessageClass();
				lbOutput.Items.Add("FacilityID, FromBreak, ToBreak");
				ICursor cursor = table.Search(null, true);
				IRow row = cursor.NextRow();
				while (row != null)
				{
					int facilityID = (int)row.get_Value(table.FindField("FacilityID"));
					double fromBreak = (double)row.get_Value(table.FindField("FromBreak"));
					double toBreak = (double)row.get_Value(table.FindField("ToBreak"));
					lbOutput.Items.Add(facilityID.ToString() + ", " + fromBreak.ToString("#####0.00") + ", " + toBreak.ToString("#####0.00"));
					row = cursor.NextRow();
				}
			}
		}

		private void UpdateMapDisplayAfterSolve()
		{
			// Zoom to the extent of the service areas
			IGeoDataset geoDataset = m_naContext.NAClasses.get_ItemByName("SAPolygons") as IGeoDataset;
			IEnvelope envelope = geoDataset.Extent;
			if (!envelope.IsEmpty)
			{
				envelope.Expand(1.1, 1.1, true);
				axMapControl.Extent = envelope;

				// Call this to update the renderer for the service area polygons
				// based on the new breaks.
				m_naContext.Solver.UpdateLayer(axMapControl.get_Layer(0) as INALayer);
			}
			axMapControl.Refresh();
		}

		#endregion
	}
}
[Visual Basic .NET]

frmServiceAreaSolver.vb

Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.NetworkAnalyst
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geometry

Namespace ServiceAreaSolver
	Partial Public Class frmServiceAreaSolver
		Inherits Form
		Private m_naContext As INAContext

#Region "Main Form Constructor and Setup"

		Public Sub New()
			InitializeComponent()

			txtCutOff.Text = "5"
			lbOutput.Items.Clear()
			cbCostAttribute.Items.Clear()
			ckbShowLines.Checked = False
			ckbUseRestriction.Checked = False
			axMapControl.ClearLayers()

			txtWorkspacePath.Text = Application.StartupPath & "\..\..\..\..\..\Data\SanFrancisco\SanFrancisco.gdb"
			txtNetworkDataset.Text = "Streets_ND"
			txtFeatureDataset.Text = "Transportation"
			txtInputFacilities.Text = "Hospitals"
			gbServiceAreaSolver.Enabled = False
		End Sub

#End Region

#Region "Button Clicks"

		Private Sub btnSolve_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSolve.Click
			Me.Cursor = Cursors.WaitCursor
			lbOutput.Items.Clear()

			ConfigureSolverSettings()

			Try
				Dim gpMessages As IGPMessages = New GPMessagesClass()
				If (Not m_naContext.Solver.Solve(m_naContext, gpMessages, Nothing)) Then
					LoadListboxAfterPartialSolve(gpMessages)
				Else
					LoadListboxAfterSuccessfulSolve()
				End If
			Catch ex As Exception
				lbOutput.Items.Add("Solve Failed: " & ex.Message)
			End Try

			UpdateMapDisplayAfterSolve()

			Me.Cursor = Cursors.Default
		End Sub

		Private Sub btnLoadMap_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnLoadMap.Click
			Me.Cursor = Cursors.WaitCursor

			gbServiceAreaSolver.Enabled = False
			lbOutput.Items.Clear()

			' Open geodatabase and network dataset
			Dim featureWorkspace As IFeatureWorkspace = Nothing
			Dim networkDataset As INetworkDataset = Nothing

			Try
				Dim workspace As IWorkspace = OpenWorkspace(Application.StartupPath & "\..\..\..\..\..\Data\SanFrancisco\SanFrancisco.gdb")
				networkDataset = OpenNetworkDataset(workspace, "Transportation", "Streets_ND")
				featureWorkspace = TryCast(workspace, IFeatureWorkspace)
			Catch ex As Exception
				Windows.Forms.MessageBox.Show("Unable to open dataset. Error Message: " + ex.Message)
				Me.Cursor = Cursors.Default
				Return
			End Try

			CreateContextAndSolver(networkDataset)
			If m_naContext Is Nothing Then
				Me.Cursor = Cursors.Default
				Return
			End If

			LoadCostAttributes(networkDataset)
			If (Not LoadLocations(featureWorkspace)) Then
				Me.Cursor = Cursors.Default
				Return
			End If

			AddNetworkDatasetLayerToMap(networkDataset)
			AddNetworkAnalysisLayerToMap()

			' work around a transparency issue
			Dim geoDataset As IGeoDataset = TryCast(networkDataset, IGeoDataset)
			axMapControl.Extent = axMapControl.FullExtent
			axMapControl.Extent = geoDataset.Extent

			If m_naContext IsNot Nothing Then
				gbServiceAreaSolver.Enabled = True
			End If

			Me.Cursor = Cursors.Default
		End Sub

#End Region

#Region "Set up Context and Solver"

		'*********************************************************************************
		' Geodatabase functions
		'*********************************************************************************
		Public Function OpenWorkspace(ByVal strGDBName As String) As IWorkspace
			' As Workspace Factories are Singleton objects, they must be instantiated with the Activator
			Dim workspaceFactory As IWorkspaceFactory = TryCast(Activator.CreateInstance(Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory")), IWorkspaceFactory)
			Return workspaceFactory.OpenFromFile(strGDBName, 0)
		End Function

		'*********************************************************************************
		' Open the network dataset
		'*********************************************************************************
		Public Function OpenNetworkDataset(ByVal workspace As IWorkspace, ByVal featureDatasetName As String, ByVal strNDSName As String) As INetworkDataset
			' Obtain the dataset container from the workspace
			Dim featureWorkspace As IFeatureWorkspace = TryCast(workspace, IFeatureWorkspace)
			Dim featureDataset As IFeatureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName)
			Dim featureDatasetExtensionContainer As IFeatureDatasetExtensionContainer = TryCast(featureDataset, IFeatureDatasetExtensionContainer)
			Dim featureDatasetExtension As IFeatureDatasetExtension = featureDatasetExtensionContainer.FindExtension(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset)
			Dim datasetContainer3 As IDatasetContainer3 = TryCast(featureDatasetExtension, IDatasetContainer3)

			' Use the container to open the network dataset
			Dim dataset As Object = datasetContainer3.DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, strNDSName)
			Return TryCast(dataset, INetworkDataset)
		End Function

		Private Sub CreateContextAndSolver(ByVal networkDataset As INetworkDataset)
			If networkDataset Is Nothing Then
				Return
			End If

			Dim datasetComponent As IDatasetComponent = TryCast(networkDataset, IDatasetComponent)
			Dim deNetworkDataset As IDENetworkDataset = TryCast(datasetComponent.DataElement, IDENetworkDataset)

			Dim naSolver As INASolver = New NAServiceAreaSolverClass()
			m_naContext = naSolver.CreateContext(deNetworkDataset, "ServiceArea")
			Dim naContextEdit As INAContextEdit = TryCast(m_naContext, INAContextEdit)
			naContextEdit.Bind(networkDataset, New GPMessagesClass())
		End Sub

#End Region

#Region "Load Form Controls"

		Private Sub LoadCostAttributes(ByVal networkDataset As INetworkDataset)
			cbCostAttribute.Items.Clear()

			Dim attrCount As Integer = networkDataset.AttributeCount
			For attrIndex As Integer = 0 To attrCount - 1
				Dim networkAttribute As INetworkAttribute = networkDataset.Attribute(attrIndex)
				If networkAttribute.UsageType = esriNetworkAttributeUsageType.esriNAUTCost Then
					cbCostAttribute.Items.Add(networkAttribute.Name)
				End If
			Next attrIndex

			If cbCostAttribute.Items.Count > 0 Then
				cbCostAttribute.SelectedIndex = 0
			End If
		End Sub

		Private Function LoadLocations(ByVal featureWorkspace As IFeatureWorkspace) As Boolean
			Dim inputFeatureClass As IFeatureClass = Nothing
			Try
				inputFeatureClass = featureWorkspace.OpenFeatureClass(txtInputFacilities.Text)
			Catch e1 As Exception
				MessageBox.Show("Specified input feature class does not exist")
				Return False
			End Try

			Dim classes As INamedSet = m_naContext.NAClasses
			Dim naClass As INAClass = TryCast(classes.ItemByName("Facilities"), INAClass)

			' delete existing locations, except barriers
			naClass.DeleteAllRows()

			' Create a NAClassLoader and set the snap tolerance (meters unit)
			Dim naClassLoader As INAClassLoader = New NAClassLoaderClass()
			naClassLoader.Locator = m_naContext.Locator
			naClassLoader.Locator.SnapTolerance = 100
			naClassLoader.NAClass = naClass

			' Create field map to automatically map fields from input class to NAClass
			Dim naClassFieldMap As INAClassFieldMap = New NAClassFieldMapClass()
			naClassFieldMap.CreateMapping(naClass.ClassDefinition, inputFeatureClass.Fields)
			naClassLoader.FieldMap = naClassFieldMap

			' Avoid loading network locations onto non-traversable portions of elements
			Dim locator As INALocator3 = TryCast(m_naContext.Locator, INALocator3)
			locator.ExcludeRestrictedElements = True
			locator.CacheRestrictedElements(m_naContext)

			' load network locations
			Dim rowsIn As Integer = 0
			Dim rowsLocated As Integer = 0
			naClassLoader.Load(TryCast(inputFeatureClass.Search(Nothing, True), ICursor), Nothing, rowsIn, rowsLocated)

			If rowsLocated <= 0 Then
				MessageBox.Show("Facilities were not loaded from input feature class")
				Return False
			End If

			' Message all of the network analysis agents that the analysis context has changed
			Dim naContextEdit As INAContextEdit = TryCast(m_naContext, INAContextEdit)
			naContextEdit.ContextChanged()

			Return True
		End Function

		Private Sub AddNetworkAnalysisLayerToMap()
			Dim layer As ILayer = TryCast(m_naContext.Solver.CreateLayer(m_naContext), ILayer)
			layer.Name = m_naContext.Solver.DisplayName
			axMapControl.AddLayer(layer)
		End Sub

		Private Sub AddNetworkDatasetLayerToMap(ByVal networkDataset As INetworkDataset)
			Dim networkLayer As INetworkLayer = New NetworkLayerClass()
			networkLayer.NetworkDataset = networkDataset
			Dim layer As ILayer = TryCast(networkLayer, ILayer)
			layer.Name = "Network Dataset"
			axMapControl.AddLayer(layer)
		End Sub

#End Region

#Region "Solver Settings"

		Private Sub ConfigureSolverSettings()
			ConfigureSettingsSpecificToServiceAreaSolver()

			ConfigureGenericSolverSettings()

			UpdateContextAfterChangingSettings()
		End Sub

		Private Sub ConfigureSettingsSpecificToServiceAreaSolver()
			Dim naSASolver As INAServiceAreaSolver = TryCast(m_naContext.Solver, INAServiceAreaSolver)

			naSASolver.DefaultBreaks = ParseBreaks(txtCutOff.Text)

			naSASolver.MergeSimilarPolygonRanges = False
			naSASolver.OutputPolygons = esriNAOutputPolygonType.esriNAOutputPolygonSimplified
			naSASolver.OverlapLines = True
			naSASolver.SplitLinesAtBreaks = False
			naSASolver.TravelDirection = esriNATravelDirection.esriNATravelDirectionFromFacility

			If ckbShowLines.Checked Then
				naSASolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShape
			Else
				naSASolver.OutputLines = esriNAOutputLineType.esriNAOutputLineNone
			End If
		End Sub

		Private Sub ConfigureGenericSolverSettings()
			Dim naSolverSettings As INASolverSettings = TryCast(m_naContext.Solver, INASolverSettings)
			naSolverSettings.ImpedanceAttributeName = cbCostAttribute.Text

			' set the oneway restriction, if necessary
			Dim restrictions As IStringArray = naSolverSettings.RestrictionAttributeNames
			restrictions.RemoveAll()
			If ckbUseRestriction.Checked Then
				restrictions.Add("oneway")
			End If
			naSolverSettings.RestrictionAttributeNames = restrictions
			naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack
		End Sub

		Private Sub UpdateContextAfterChangingSettings()
			Dim datasetComponent As IDatasetComponent = TryCast(m_naContext.NetworkDataset, IDatasetComponent)
			Dim deNetworkDataset As IDENetworkDataset = TryCast(datasetComponent.DataElement, IDENetworkDataset)
			m_naContext.Solver.UpdateContext(m_naContext, deNetworkDataset, New GPMessagesClass())
		End Sub

		Private Function ParseBreaks(ByVal p As String) As IDoubleArray
			Dim breaks() As String = p.Split(" "c)
			Dim pBrks As IDoubleArray = New DoubleArrayClass()
			Dim firstIndex As Integer = breaks.GetLowerBound(0)
			Dim lastIndex As Integer = breaks.GetUpperBound(0)
			For splitIndex As Integer = firstIndex To lastIndex
				Try
					pBrks.Add(Convert.ToDouble(breaks(splitIndex)))
				Catch e1 As FormatException
					MessageBox.Show("Breaks are not properly formatted.  Use only digits separated by spaces")
					pBrks.RemoveAll()
					Return pBrks
				End Try
			Next splitIndex

			Return pBrks
		End Function

#End Region

#Region "Post-Solve"

		Private Sub LoadListboxAfterPartialSolve(ByVal gpMessages As IGPMessages)
			lbOutput.Items.Add("Partial Solve Generated.")
			For msgIndex As Integer = 0 To gpMessages.Messages.Count - 1
				Dim errorText As String = ""
				Select Case gpMessages.GetMessage(msgIndex).Type
					Case esriGPMessageType.esriGPMessageTypeError
						errorText = "Error " & gpMessages.GetMessage(msgIndex).ErrorCode.ToString() & " " & gpMessages.GetMessage(msgIndex).Description
					Case esriGPMessageType.esriGPMessageTypeWarning
						errorText = "Warning " & gpMessages.GetMessage(msgIndex).ErrorCode.ToString() & " " & gpMessages.GetMessage(msgIndex).Description
					Case Else
						errorText = "Information " & gpMessages.GetMessage(msgIndex).Description
				End Select
				lbOutput.Items.Add(errorText)
			Next msgIndex
		End Sub

		Private Sub LoadListboxAfterSuccessfulSolve()
			Dim table As ITable = TryCast(m_naContext.NAClasses.ItemByName("SAPolygons"), ITable)
			If table.RowCount(Nothing) > 0 Then
				Dim gpMessage As IGPMessage = New GPMessageClass()
				lbOutput.Items.Add("FacilityID, FromBreak, ToBreak")
				Dim cursor As ICursor = table.Search(Nothing, True)
				Dim row As IRow = cursor.NextRow()
				Do While row IsNot Nothing
					Dim facilityID As Integer = CInt(Fix(row.Value(table.FindField("FacilityID"))))
					Dim fromBreak As Double = CDbl(row.Value(table.FindField("FromBreak")))
					Dim toBreak As Double = CDbl(row.Value(table.FindField("ToBreak")))
					lbOutput.Items.Add(facilityID.ToString() & ", " & fromBreak.ToString("#####0.00") & ", " & toBreak.ToString("#####0.00"))
					row = cursor.NextRow()
				Loop
			End If
		End Sub

		Private Sub UpdateMapDisplayAfterSolve()
			' Zoom to the extent of the service areas
			Dim geoDataset As IGeoDataset = TryCast(m_naContext.NAClasses.ItemByName("SAPolygons"), IGeoDataset)
			Dim envelope As IEnvelope = geoDataset.Extent
			If (Not envelope.IsEmpty) Then
				envelope.Expand(1.1, 1.1, True)
				axMapControl.Extent = envelope

				' Call this to update the renderer for the service area polygons
				' based on the new breaks.
				m_naContext.Solver.UpdateLayer(TryCast(axMapControl.get_Layer(0), INALayer))
			End If
			axMapControl.Refresh()
		End Sub

#End Region
	End Class
End Namespace