About the Closest facility solver Sample
[C#]
frmClosestFacilitySolver.cs
//*************************************************************************************
// ArcGIS Network Analyst extension - Closest Facility Demonstration
//
// This simple code shows how to :
// 1) Open a workspace and open a Network DataSet
// 2) Create a NAContext and its NASolver
// 3) Load Incidents/Facilites from Feature Classes and create Network Locations
// 4) Set the Solver parameters
// 5) Solve a Closest Facility problem
// 6) Read the CFRoutes output to display the total facilities
// and the list of the routes found
//************************************************************************************
using System;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.NetworkAnalyst;
namespace ClosestFacilitySolver
{
public partial class frmClosestFacilitySolver : Form
{
private INAContext m_NAContext;
private readonly string OUTPUTCLASSNAME = "CFRoutes";
#region Main Form Constructor and Setup
public frmClosestFacilitySolver()
{
InitializeComponent();
Initialize();
}
/// <summary>
/// Initialize the solver by calling the ArcGIS Network Analyst extension functions.
/// </summary>
private void Initialize()
{
IFeatureWorkspace featureWorkspace = null;
INetworkDataset networkDataset = null;
try
{
// Open Geodatabase and network dataset
IWorkspace workspace = OpenWorkspace(Application.StartupPath + @"\..\..\..\..\..\Data\SanFrancisco\SanFrancisco.gdb");
networkDataset = OpenNetworkDataset(workspace, "Transportation", "Streets_ND");
featureWorkspace = workspace as IFeatureWorkspace;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Unable to open dataset. Error Message: " + ex.Message);
this.Close();
return;
}
// Create NAContext and NASolver
CreateSolverContext(networkDataset);
// Get available cost attributes from the network dataset
INetworkAttribute networkAttribute;
for (int i = 0; i < networkDataset.AttributeCount - 1; i++)
{
networkAttribute = networkDataset.get_Attribute(i);
if (networkAttribute.UsageType == esriNetworkAttributeUsageType.esriNAUTCost)
{
cboCostAttribute.Items.Add(networkAttribute.Name);
}
}
cboCostAttribute.SelectedIndex = 0;
txtTargetFacility.Text = "1";
txtCutOff.Text = "";
// Load incidents from a feature class
IFeatureClass inputFClass = featureWorkspace.OpenFeatureClass("Stores");
LoadNANetworkLocations("Incidents", inputFClass, 500);
// Load facilities from a feature class
inputFClass = featureWorkspace.OpenFeatureClass("FireStations");
LoadNANetworkLocations("Facilities", inputFClass, 500);
//Create Layer for Network Dataset and add to ArcMap
INetworkLayer networkLayer = new NetworkLayerClass();
networkLayer.NetworkDataset = networkDataset;
var layer = networkLayer as ILayer;
layer.Name = "Network Dataset";
axMapControl.AddLayer(layer, 0);
//Create a Network Analysis Layer and add to ArcMap
INALayer naLayer = m_NAContext.Solver.CreateLayer(m_NAContext);
layer = naLayer as ILayer;
layer.Name = m_NAContext.Solver.DisplayName;
axMapControl.AddLayer(layer, 0);
}
#endregion
#region Button Clicks
/// <summary>
/// Call the Closest Facility cost matrix solver and display the results
/// </summary>
/// <param name="sender">Sender of the event</param>
/// <param name="e">Event</param>
private void cmdSolve_Click(object sender, System.EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
lstOutput.Items.Clear();
IGPMessages gpMessages = new GPMessagesClass();
try
{
lstOutput.Items.Add("Solving...");
SetSolverSettings();
if (!m_NAContext.Solver.Solve(m_NAContext, gpMessages, null))
lstOutput.Items.Add("Partial Solve Generated.");
DisplayOutput();
}
catch (Exception ee)
{
lstOutput.Items.Add("Failure: " + ee.Message);
}
lstOutput.Items.Add(GetGPMessagesAsString(gpMessages));
cmdSolve.Text = "Find Closest Facilities";
RefreshMapDisplay();
this.Cursor = Cursors.Default;
}
#endregion
#region Set up Context and Solver
/// <summary>
/// Geodatabase function: open work space
/// </summary>
/// <param name="strGDBName">Input file name</param>
/// <returns>Workspace</returns>
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(strGDBName))
{
MessageBox.Show("The workspace: " + strGDBName + " does not exist", "Workspace Error");
return null;
}
IWorkspace workspace = null;
try
{
workspace = workspaceFactory.OpenFromFile(strGDBName, 0);
}
catch (Exception ex)
{
MessageBox.Show("Opening workspace failed: " + ex.Message, "Workspace Error");
}
return workspace;
}
/// <summary>
/// Geodatabase function: open network dataset
/// </summary>
/// <param name="workspace">Input workspace</param>
/// <param name="strNDSName">Input network dataset name</param>
/// <returns>NetworkDataset</returns>
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;
}
/// <summary>
/// Geodatabase function: get network dataset
/// </summary>
/// <param name="networkDataset">Input network dataset</param>
/// <returns>DE network dataset</returns>
public IDENetworkDataset GetDENetworkDataset(INetworkDataset networkDataset)
{
// Cast from the network dataset to the DatasetComponent
IDatasetComponent dsComponent = networkDataset as IDatasetComponent;
// Get the data element
return dsComponent.DataElement as IDENetworkDataset;
}
/// <summary>
/// Create NASolver and NAContext
/// </summary>
/// <param name="networkDataset">Input network dataset</param>
/// <returns>NAContext</returns>
public void CreateSolverContext(INetworkDataset networkDataset)
{
if (networkDataset == null) return;
//Get the Data Element
IDENetworkDataset deNDS = GetDENetworkDataset(networkDataset);
INASolver naSolver = new NAClosestFacilitySolver();
m_NAContext = naSolver.CreateContext(deNDS, naSolver.Name);
((INAContextEdit)m_NAContext).Bind(networkDataset, new GPMessagesClass());
}
/// <summary>
/// Set solver settings
/// </summary>
/// <param name="strNAClassName">NAClass name</param>
/// <param name="inputFC">Input feature class</param>
/// <param name="maxSnapTolerance">Max snap tolerance</param>
public void LoadNANetworkLocations(string strNAClassName, IFeatureClass inputFC, double maxSnapTolerance)
{
INamedSet classes = m_NAContext.NAClasses;
INAClass naClass = classes.get_ItemByName(strNAClassName) as INAClass;
// delete existing Locations except if that a barriers
naClass.DeleteAllRows();
// Create a NAClassLoader and set the snap tolerance (meters unit)
INAClassLoader classLoader = new NAClassLoader();
classLoader.Locator = m_NAContext.Locator;
if (maxSnapTolerance > 0) ((INALocator3)classLoader.Locator).MaxSnapTolerance = maxSnapTolerance;
classLoader.NAClass = naClass;
//Create field map to automatically map fields from input class to NAClass
INAClassFieldMap fieldMap = new NAClassFieldMapClass();
fieldMap.CreateMapping(naClass.ClassDefinition, inputFC.Fields);
classLoader.FieldMap = fieldMap;
// 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;
IFeatureCursor featureCursor = inputFC.Search(null, true);
classLoader.Load((ICursor)featureCursor, null, ref rowsIn, ref rowsLocated);
//Message all of the network analysis agents that the analysis context has changed
((INAContextEdit)m_NAContext).ContextChanged();
}
#endregion
#region Post-Solve
/// <summary>
/// Display analysis results in the list box
/// </summary>
public void DisplayOutput()
{
ITable table = m_NAContext.NAClasses.get_ItemByName(OUTPUTCLASSNAME) as ITable;
if (table == null)
{
lstOutput.Items.Add("Impossible to get the " + OUTPUTCLASSNAME + " table");
}
lstOutput.Items.Add("Number facilities found " + table.RowCount(null).ToString());
lstOutput.Items.Add("");
if (table.RowCount(null) > 0)
{
lstOutput.Items.Add("IncidentID, FacilityID,FacilityRank,Total_" + cboCostAttribute.Text);
double total_impedance;
long incidentID;
long facilityID;
long facilityRank;
ICursor cursor;
IRow row;
cursor = table.Search(null, false);
row = cursor.NextRow();
while (row != null)
{
incidentID = long.Parse(row.get_Value(table.FindField("IncidentID")).ToString());
facilityID = long.Parse(row.get_Value(table.FindField("FacilityID")).ToString());
facilityRank = long.Parse(row.get_Value(table.FindField("FacilityRank")).ToString());
total_impedance = double.Parse(row.get_Value(table.FindField("Total_" + cboCostAttribute.Text)).ToString());
lstOutput.Items.Add(incidentID.ToString() + ",\t" + facilityID.ToString() +
",\t" + facilityRank.ToString() + ",\t" + total_impedance.ToString("F2"));
row = cursor.NextRow();
}
}
lstOutput.Refresh();
}
/// <summary>
/// Gather the error/warning/informative messages from GPMessages
/// <summary>
/// <param name="gpMessages">GPMessages container</param>
/// <returns>string of all GPMessages</returns>
public string GetGPMessagesAsString(IGPMessages gpMessages)
{
// Gather Error/Warning/Informative Messages
var messages = new StringBuilder();
if (gpMessages != null)
{
for (int i = 0; i < gpMessages.Count; i++)
{
IGPMessage gpMessage = gpMessages.GetMessage(i);
string message = gpMessage.Description;
switch (gpMessages.GetMessage(i).Type)
{
case esriGPMessageType.esriGPMessageTypeError:
messages.AppendLine("Error " + gpMessage.ErrorCode + ": " + message);
break;
case esriGPMessageType.esriGPMessageTypeWarning:
messages.AppendLine("Warning: " + message);
break;
default:
messages.AppendLine("Information: " + message);
break;
}
}
}
return messages.ToString();
}
/// <summary>
/// Refresh the map display
/// <summary>
public void RefreshMapDisplay()
{
// Zoom to the extent of the service areas
IGeoDataset geoDataset = m_NAContext.NAClasses.get_ItemByName(OUTPUTCLASSNAME) as IGeoDataset;
IEnvelope envelope = geoDataset.Extent;
if (!envelope.IsEmpty)
{
envelope.Expand(1.1, 1.1, true);
axMapControl.Extent = envelope;
m_NAContext.Solver.UpdateLayer(axMapControl.get_Layer(0) as INALayer);
}
axMapControl.Refresh();
}
#endregion
#region Solver Settings
/// <summary>
/// Set solver settings
/// </summary>
public void SetSolverSettings()
{
//Set Route specific Settings
INASolver naSolver = m_NAContext.Solver;
INAClosestFacilitySolver cfSolver = naSolver as INAClosestFacilitySolver;
if (txtCutOff.Text.Length > 0 && IsNumeric(txtCutOff.Text.Trim()))
cfSolver.DefaultCutoff = txtCutOff.Text;
else
cfSolver.DefaultCutoff = null;
if (txtTargetFacility.Text.Length > 0 && IsNumeric(txtTargetFacility.Text))
cfSolver.DefaultTargetFacilityCount = int.Parse(txtTargetFacility.Text);
else
cfSolver.DefaultTargetFacilityCount = 1;
cfSolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShapeWithMeasure;
cfSolver.TravelDirection = esriNATravelDirection.esriNATravelDirectionToFacility;
// Set generic solver settings
// Set the impedance attribute
INASolverSettings naSolverSettings;
naSolverSettings = naSolver as INASolverSettings;
naSolverSettings.ImpedanceAttributeName = cboCostAttribute.Text;
// Set the OneWay Restriction if necessary
IStringArray restrictions;
restrictions = naSolverSettings.RestrictionAttributeNames;
restrictions.RemoveAll();
if (chkUseRestriction.Checked)
restrictions.Add("oneway");
naSolverSettings.RestrictionAttributeNames = restrictions;
//Restrict UTurns
naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack;
naSolverSettings.IgnoreInvalidLocations = true;
// Set the Hierarchy attribute
naSolverSettings.UseHierarchy = chkUseHierarchy.Checked;
if (naSolverSettings.UseHierarchy)
naSolverSettings.HierarchyAttributeName = "HierarchyMultiNet";
// Do not forget to update the context after you set your impedance
naSolver.UpdateContext(m_NAContext, GetDENetworkDataset(m_NAContext.NetworkDataset), new GPMessagesClass());
}
/// <summary>
/// Check whether a string represents a double value.
/// </summary>
/// <param name="str">String to test</param>
/// <returns>bool</returns>
private bool IsNumeric(string str)
{
try
{
double.Parse(str.Trim());
}
catch (Exception)
{
return false;
}
return true;
}
#endregion
}
}
[Visual Basic .NET]
frmClosestFacilitySolver.vb
'*************************************************************************************
' ArcGIS Network Analyst extension - Closest Facility Demonstration
'
' This simple code shows how to :
' 1) Open an shapefile workspace and open a Network DataSet
' 2) Create a NAContext and its NASolver
' 3) Load Incidents/Facilites from Feature Classes and create Network Locations
' 4) Set the Solver parameters
' 5) Solve a Closest Facility problem
' 6) Read the CFRoutes output to display the total facilities
' and the list of the routes found
'************************************************************************************
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.NetworkAnalyst
Public Class frmClosestFacilitySolver
Private m_NAContext As INAContext
Public Sub New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Initialize()
End Sub
'*********************************************************************************
' Initialize the form, create a NA context, load some locations and draw the map
'*********************************************************************************
Private Sub Initialize()
' 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.Close()
Return
End Try
' Create NAContext and NASolver
m_NAContext = CreateSolverContext(networkDataset)
' Get Cost Attributes and populate the combo drop down box
Dim networkAttribute As INetworkAttribute
For i As Integer = 0 To networkDataset.AttributeCount - 2
networkAttribute = networkDataset.Attribute(i)
If networkAttribute.UsageType = esriNetworkAttributeUsageType.esriNAUTCost Then
cboCostAttribute.Items.Add(networkAttribute.Name)
cboCostAttribute.SelectedIndex = 0
End If
Next
txtTargetFacility.Text = "1"
txtCutOff.Text = "<None>"
' Load incidents from FC
Dim inputFClass As IFeatureClass = featureWorkspace.OpenFeatureClass("Stores")
LoadNANetworkLocations("Incidents", inputFClass, 100)
' Load facilities from FC
inputFClass = featureWorkspace.OpenFeatureClass("FireStations")
LoadNANetworkLocations("Facilities", inputFClass, 100)
' Create Layer for Network Dataset and add to ArcMap
Dim networkLayer As INetworkLayer = New NetworkLayerClass
networkLayer.NetworkDataset = networkDataset
Dim layer As ILayer = TryCast(networkLayer, ILayer)
layer.Name = "Network Dataset"
axMapControl.AddLayer(layer, 0)
' Create a Network Analysis Layer and add to ArcMap
Dim naLayer As INALayer = m_NAContext.Solver.CreateLayer(m_NAContext)
layer = naLayer
layer.Name = m_NAContext.Solver.DisplayName
axMapControl.AddLayer(layer, 0)
End Sub
'*********************************************************************************
' ArcGIS Network Analyst extension functions
' ********************************************************************************
'*********************************************************************************
' Create NASolver and NAContext
'*********************************************************************************
Public Function CreateSolverContext(ByVal networkDataset As INetworkDataset) As INAContext
' Get the Data Element
Dim deNDS As IDENetworkDataset = GetDENetworkDataset(networkDataset)
Dim naSolver As INASolver = New NAClosestFacilitySolver
Dim contextEdit As INAContextEdit = naSolver.CreateContext(deNDS, naSolver.Name)
contextEdit.Bind(networkDataset, New GPMessagesClass)
Return TryCast(contextEdit, INAContext)
End Function
'*********************************************************************************
' Load network locations
'*********************************************************************************
Public Sub LoadNANetworkLocations(ByVal strNAClassName As String, ByVal inputFC As IFeatureClass, ByVal maxSnapTolerance As Double)
Dim classes As INamedSet = m_NAContext.NAClasses
Dim naClass As INAClass = TryCast(classes.ItemByName(strNAClassName), INAClass)
' delete existing Locations except if that a barriers
naClass.DeleteAllRows()
' 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)
' Create a NAClassLoader and set the maximum snap tolerance (meters unit)
Dim classLoader As INAClassLoader = New NAClassLoader
classLoader.Locator = m_NAContext.Locator
If maxSnapTolerance > 0 Then
locator.MaxSnapTolerance = maxSnapTolerance
End If
classLoader.NAClass = naClass
' Create field map to automatically map fields from input class to naclass
Dim fieldMap As INAClassFieldMap = New NAClassFieldMap
fieldMap.CreateMapping(naClass.ClassDefinition, inputFC.Fields)
classLoader.FieldMap = fieldMap
' Load Network Locations
Dim rowsIn As Integer = 0
Dim rowsLocated As Integer = 0
Dim featureCursor As IFeatureCursor = inputFC.Search(Nothing, True)
classLoader.Load(featureCursor, Nothing, rowsIn, rowsLocated)
' Message all of the network analysis agents that the analysis context has changed
CType(m_NAContext, INAContextEdit).ContextChanged()
End Sub
'*********************************************************************************
' Set Solver Settings
'*********************************************************************************
Public Sub SetSolverSettings()
'Set Route specific Settings
Dim naSolver As INASolver = m_NAContext.Solver
Dim cfSolver As INAClosestFacilitySolver = TryCast(naSolver, INAClosestFacilitySolver)
' Set number of facilities to find
If txtTargetFacility.Text.Length > 0 And IsNumeric(txtTargetFacility.Text) Then
cfSolver.DefaultTargetFacilityCount = Integer.Parse(txtTargetFacility.Text)
Else
cfSolver.DefaultTargetFacilityCount = 1
End If
' Set impedance cutoff
If txtCutOff.Text.Length > 0 And IsNumeric(txtCutOff.Text.Trim()) Then
cfSolver.DefaultCutoff = txtCutOff.Text
Else
cfSolver.DefaultCutoff = Nothing
End If
cfSolver.OutputLines = esriNAOutputLineType.esriNAOutputLineTrueShapeWithMeasure
cfSolver.TravelDirection = esriNATravelDirection.esriNATravelDirectionToFacility
'Set generic Solver settings
' set the impedance attribute
Dim naSolverSettings As INASolverSettings = naSolver
naSolverSettings.ImpedanceAttributeName = cboCostAttribute.Text
' Set the OneWay Restriction if necessary
Dim restrictions As IStringArray = naSolverSettings.RestrictionAttributeNames
restrictions.RemoveAll()
If chkUseRestriction.Checked Then
restrictions.Add("oneway")
End If
naSolverSettings.RestrictionAttributeNames = restrictions
'Restrict UTurns
naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack
naSolverSettings.IgnoreInvalidLocations = True
' Set the Hierarchy attribute
naSolverSettings.UseHierarchy = chkUseHierarchy.Checked
If naSolverSettings.UseHierarchy Then
naSolverSettings.HierarchyAttributeName = "HierarchyMultiNet"
End If
' Do not forget to update the context after you set your impedance
naSolver.UpdateContext(m_NAContext, GetDENetworkDataset(m_NAContext.NetworkDataset), New GPMessagesClass)
End Sub
'*********************************************************************************
' 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
Public Function GetDENetworkDataset(ByVal pNetDataset As INetworkDataset) As IDENetworkDataset
'Cast from the Network Dataset to the DatasetComponent
Dim dsComponent As IDatasetComponent = pNetDataset
'Get the Data Element
Return TryCast(dsComponent.DataElement, IDENetworkDataset)
End Function
Private Sub cmdSolve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSolve.Click
Dim gpMessages As IGPMessages = New GPMessagesClass
Try
lstOutput.Items.Clear()
lstOutput.Items.Add("Solving...")
SetSolverSettings()
' Solve
If Not m_NAContext.Solver.Solve(m_NAContext, gpMessages, Nothing) Then
lstOutput.Items.Add("Partial Result")
End If
DisplayOutput()
Catch ee As Exception
lstOutput.Items.Add("Failure: " + ee.Message)
End Try
lstOutput.Items.Add(GetGPMessagesAsString(gpMessages))
cmdSolve.Text = "Find Closest Facilities"
End Sub
Private Sub UpdateMapDisplayAfterSolve()
' Zoom to the extent of the service areas
Dim geoDataset As IGeoDataset = TryCast(m_NAContext.NAClasses.ItemByName("CFRoutes"), 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
'*********************************************************************************
' Gather the error/warning/informative messages from GPMessages
'*********************************************************************************
Public Function GetGPMessagesAsString(ByVal gpMessages As IGPMessages) As String
Dim messages As System.Text.StringBuilder = New System.Text.StringBuilder()
If Not gpMessages Is Nothing Then
Dim i As Integer
For i = 0 To gpMessages.Count - 1
Dim gpMessage As IGPMessage = gpMessages.GetMessage(i)
Dim message As String = gpMessage.Description
Select Case gpMessage.Type
Case esriGPMessageType.esriGPMessageTypeError
messages.AppendLine("Error " + gpMessage.ErrorCode.ToString + ": " + message)
Case esriGPMessageType.esriGPMessageTypeWarning
messages.AppendLine("Warning: " + message)
Case Else
messages.AppendLine("Information: " + message)
End Select
Next
End If
Return messages.ToString()
End Function
' Get the Impedance Cost form the CFRoute Class Output
Public Sub DisplayOutput()
Dim strNAClass As String = "CFRoutes"
Dim table As ITable = m_NAContext.NAClasses.ItemByName(strNAClass)
If table Is Nothing Then
lstOutput.Items.Add("Impossible to get the " + strNAClass + " table")
End If
lstOutput.Items.Add("Number facilities found " + table.RowCount(Nothing).ToString())
lstOutput.Items.Add("")
If table.RowCount(Nothing) > 0 Then
lstOutput.Items.Add("IncidentID, FacilityID, FacilityRank, Total_" + cboCostAttribute.Text)
Dim total_impedance As Double
Dim incidentID As Long
Dim facilityID As Long
Dim facilityRank As Long
Dim cursor As ICursor
Dim row As IRow
cursor = table.Search(Nothing, False)
row = cursor.NextRow()
While Not row Is Nothing
incidentID = Long.Parse(row.Value(table.FindField("IncidentID")).ToString())
facilityID = Long.Parse(row.Value(table.FindField("FacilityID")).ToString())
facilityRank = Long.Parse(row.Value(table.FindField("FacilityRank")).ToString())
total_impedance = Double.Parse(row.Value(table.FindField("Total_" + cboCostAttribute.Text)).ToString())
lstOutput.Items.Add(incidentID.ToString() + "," + vbTab + facilityID.ToString() + "," + vbTab + facilityRank.ToString() + "," + vbTab + total_impedance.ToString("F2"))
row = cursor.NextRow()
End While
End If
lstOutput.Refresh()
End Sub
Private Function IsNumeric(ByVal str As String) As Boolean
Try
Double.Parse(str.Trim())
Catch
Return False
End Try
Return True
End Function
End Class