ArcGIS二次开发基础教程(13):网络分析之最近设施分析
最近设施分析
/// <summary>
/// Geodatabase function: open work space
/// </summary>
/// <param name="strGDBName">Input file name</param>
/// <returns>Workspace</returns>
public IWorkspace OpenWorkspace(string strMDBName)
{
// As Workspace Factories are Singleton objects, they must be instantiated with the Activator
var workspaceFactory = System.Activator.CreateInstance(System.Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory")) as ESRI.ArcGIS.Geodatabase.IWorkspaceFactory;
if (!System.IO.File.Exists(strMDBName))
{
MessageBox.Show("The workspace: " + strMDBName + " does not exist", "Workspace Error");
return null;
}
IWorkspace workspace = null;
try
{
workspace = workspaceFactory.OpenFromFile(strMDBName, 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>
private void CreateSolverContext(INetworkDataset networkDataset)
{
if (networkDataset == null) return;
//Get the Data Element
IDENetworkDataset deNDS = GetDENetworkDataset(networkDataset);
INASolver naSolver = new NAClosestFacilitySolverClass();
f_NAContext = naSolver.CreateContext(deNDS, naSolver.Name);
((INAContextEdit)f_NAContext).Bind(networkDataset, new GPMessagesClass());
}
/// <summary>
/// Create a layer for the network dataset and add it to the map
/// </summary>
private void AddNetworkDatasetLayerToMap(INetworkDataset networkDataset)
{
INetworkLayer networkLayer = new NetworkLayerClass();
networkLayer.NetworkDataset = networkDataset;
ILayer layer = networkLayer as ILayer;
layer.Name = "CF_ND";
axMapControl1.AddLayer(layer);
}
/// <summary>
/// Create a layer from the context and add it to the map
/// </summary>
private void AddNetworkAnalysisLayerToMap()
{
ILayer layer = f_NAContext.Solver.CreateLayer(f_NAContext) as ILayer;
layer.Name = f_NAContext.Solver.DisplayName;
axMapControl1.AddLayer(layer);
}
private INAContext f_NAContext;//网络分析上下文
private IFeatureClass incidentsFeatureClass;//事故点
private IFeatureClass facilitiesFeatureClass;//设施点
private IGraphicsContainer gra;
private IActiveView act;
private bool CFNA = false;//分析准备
private int incidentsCount = 0;//事故点
private int facilitiesCount = 0;//设施点
private void 打开网络数据集ToolStripMenuItem2_Click(object sender, EventArgs e)
{
IFeatureWorkspace featureWorkspace = null;
INetworkDataset networkDataset1 = null;
openFileDialog1.Title = "打开网络数据集";
openFileDialog1.Filter = "Peronal GeoDatabase(*.mdb)|*.mdb";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
// Open Geodatabase and network dataset
IWorkspace workspace = OpenWorkspace(openFileDialog1.FileName);
networkDataset1 = OpenNetworkDataset(workspace, "CF", "CF_ND");
featureWorkspace = workspace as IFeatureWorkspace;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Unable to open dataset. Error Message: " + ex.Message);
this.Close();
return;
}
//创建网络上下文
CreateSolverContext(networkDataset1);
//从工作空间获得用来存储输入点的要素类
incidentsFeatureClass = featureWorkspace.OpenFeatureClass("incidents");
facilitiesFeatureClass = featureWorkspace.OpenFeatureClass("facilities");
//获得道路和节点图层
IFeatureClass road = featureWorkspace.OpenFeatureClass("road");
IFeatureClass junctions = featureWorkspace.OpenFeatureClass("CF_ND_Junctions");
//把以上四个图层全部添加进地图
IFeatureLayer layer1 = new FeatureLayerClass();
IFeatureClass class1 = incidentsFeatureClass;
layer1.FeatureClass = class1;
layer1.Name = class1.AliasName;
axMapControl1.AddLayer(layer1);
IFeatureLayer layer2 = new FeatureLayerClass();
IFeatureClass class2 = facilitiesFeatureClass;
layer2.FeatureClass = class2;
layer2.Name = class2.AliasName;
axMapControl1.AddLayer(layer2);
IFeatureLayer layer3 = new FeatureLayerClass();
layer3.FeatureClass = road;
layer3.Name = road.AliasName;
axMapControl1.AddLayer(layer3);
IFeatureLayer layer4 = new FeatureLayerClass();
layer4.FeatureClass = junctions;
layer4.Name = junctions.AliasName;
axMapControl1.AddLayer(layer4);
//添加网络数据集图层和网络分析图层
AddNetworkDatasetLayerToMap(networkDataset1);
AddNetworkAnalysisLayerToMap();
gra = axMapControl1.ActiveView.FocusMap as IGraphicsContainer;
act = axMapControl1.ActiveView;
axMapControl1.Refresh();
}
}
private void 分析准备ToolStripMenuItem2_Click(object sender, EventArgs e)
{
CFNA = true;
//清除输入设施点
ITable table = facilitiesFeatureClass as ITable;
table.DeleteSearchedRows(null);
//清除输入事故点
ITable table2 = incidentsFeatureClass as ITable;
table2.DeleteSearchedRows(null);
//清除网络分析图层设施点
INAClass class1 = f_NAContext.NAClasses.get_ItemByName("Facilities") as INAClass;
ITable table3 = class1 as ITable;
table3.DeleteSearchedRows(null);
//清除网络分析图层事故点
INAClass class2 = f_NAContext.NAClasses.get_ItemByName("Incidents") as INAClass;
ITable table4 = class2 as ITable;
table4.DeleteSearchedRows(null);
//清楚路线
INAClass class3 = f_NAContext.NAClasses.get_ItemByName("CFRoutes") as INAClass;
ITable table5 = class3 as ITable;
table5.DeleteSearchedRows(null);
//清除障碍
INAClass class4 = f_NAContext.NAClasses.get_ItemByName("Barriers") as INAClass;
ITable table6 = class4 as ITable;
table6.DeleteSearchedRows(null);
//点号清零
facilitiesCount = 0;
incidentsCount = 0;
//元素清零
gra.DeleteAllElements();
act.Refresh();
//提醒
MessageBox.Show("可开始选择点");
}
private void ChooseIncidents(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (CFNA == true)//如果分析准备好了就添加要素点
{
IPoint pt = new PointClass();
pt = act.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
IFeature feature = incidentsFeatureClass.CreateFeature();
feature.Shape = pt;
feature.Store();
incidentsCount++;
//在地图上显示当前站点数目
ITextElement textElement = new TextElementClass();
ITextSymbol ts = new TextSymbolClass();
IRgbColor color = new RgbColorClass();
color.RGB = 38;
ts.Color = color;
textElement.Symbol = ts;
textElement.Text = incidentsCount.ToString();
IElement ele = textElement as IElement;
ele.Geometry = pt;
gra.AddElement(ele, 0);
act.Refresh();
}
}
private void ChooseFacilities(object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (CFNA == true)
{
IPoint pt = new PointClass();
pt = act.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
IFeature feature = facilitiesFeatureClass.CreateFeature();
feature.Shape = pt;
feature.Store();
facilitiesCount++;
ITextElement textElement = new TextElementClass();
ITextSymbol ts = new TextSymbolClass();
IRgbColor color = new RgbColorClass();
color.RGB = 196;
ts.Color = color;
textElement.Symbol = ts;
textElement.Text = facilitiesCount.ToString();
IElement ele = textElement as IElement;
ele.Geometry = pt;
gra.AddElement(ele, 0);
act.Refresh();
}
}
/// <summary>
/// Set solver settings
/// </summary>
/// <param name="strNAClassName">NAClass name</param>
/// <param name="inputFC">Input feature class</param>
public void LoadNANetworkLocations(string strNAClassName, IFeatureClass inputFC)
{
INamedSet classes = f_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 = f_NAContext.Locator;
((INALocator3)classLoader.Locator).MaxSnapTolerance = 80;
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 = f_NAContext.Locator as INALocator3;
locator.ExcludeRestrictedElements = true;
locator.CacheRestrictedElements(f_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)f_NAContext).ContextChanged();
}
private void 实施分析ToolStripMenuItem2_Click(object sender, EventArgs e)
{
IGPMessages messages = new GPMessagesClass();
//加载站点 设施点和事故点
LoadNANetworkLocations("Incidents", incidentsFeatureClass);
LoadNANetworkLocations("Facilities", facilitiesFeatureClass);
f_NAContext.Solver.Solve(f_NAContext, messages, null);
//每次实施分析后把输入要素清空
ITable table = incidentsFeatureClass as ITable;
table.DeleteSearchedRows(null);
ITable table2 = facilitiesFeatureClass as ITable;
table.DeleteSearchedRows(null);
axMapControl1.Refresh();
}
还可以将分析结果以文本形式显示出来
//需要一个ListBox控件
/// <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_Length" );
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_Length")).ToString());
lstOutput.Items.Add(incidentID.ToString() + ",\t" + facilityID.ToString() +
",\t" + facilityRank.ToString() + ",\t" + total_impedance.ToString("F2"));
row = cursor.NextRow();
}
}