基于网络数据集的最短路径
基于网络数据集的最短路径
在网络找了很久还是没有找到关于网络数据集最短路径分析,全是基于几何网络的,昨天参照AE的ClosestFacilitySolver实例和网上网友发布的在内存建立图层的方法完成了网络数据集的最短路径分析,功能还是比较粗糙,对于高手应该很简单,但是对于刚接触AE的朋友也算是抛砖引玉了。 贴出主要函数: //打开网络数据集 public INetworkDataset OpenNetworkDataset(IWorkspace networkDatasetWorkspace, System.String networkDatasetName, System.String featureDatasetName) { if (networkDatasetWorkspace == null || networkDatasetName == "" || featureDatasetName == null) { return null; } IDatasetContainer3 datasetContainer3 = null; switch (networkDatasetWorkspace.Type) { case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriFileSystemWorkspace: // Shapefile or SDC network dataset workspace IWorkspaceExtensionManager workspaceExtensionManager = networkDatasetWorkspace as ESRI.ArcGIS.Geodatabase.IWorkspaceExtensionManager; // Dynamic Cast ESRI.ArcGIS.esriSystem.UID networkID = new ESRI.ArcGIS.esriSystem.UIDClass(); networkID.Value = "esriGeoDatabase.NetworkDatasetWorkspaceExtension"; ESRI.ArcGIS.Geodatabase.IWorkspaceExtension workspaceExtension = workspaceExtensionManager.FindExtension(networkID); datasetContainer3 = workspaceExtension as IDatasetContainer3; // Dynamic Cast break; case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriLocalDatabaseWorkspace: // Personal Geodatabase or File Geodatabase network dataset workspace case ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriRemoteDatabaseWorkspace: // SDE Geodatabase network dataset workspace ESRI.ArcGIS.Geodatabase.IFeatureWorkspace featureWorkspace = networkDatasetWorkspace as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace; // Dynamic Cast featureDataset = featureWorkspace.OpenFeatureDataset(featureDatasetName); ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer featureDatasetExtensionContainer = featureDataset as ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtensionContainer; // Dynamic Cast ESRI.ArcGIS.Geodatabase.IFeatureDatasetExtension featureDatasetExtension = featureDatasetExtensionContainer.FindExtension(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset); datasetContainer3 = featureDatasetExtension as ESRI.ArcGIS.Geodatabase.IDatasetContainer3; // Dynamic Cast break; } if (datasetContainer3 == null) return null; ESRI.ArcGIS.Geodatabase.IDataset dataset = datasetContainer3.get_DatasetByName(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTNetworkDataset, networkDatasetName); return dataset as ESRI.ArcGIS.Geodatabase.INetworkDataset; // Dynamic Cast } //创建网络分析上下文 public INAContext CreateSolverContext(INetworkDataset networkDataset) { IDENetworkDataset deNDS = GetDENetworkDataset(networkDataset); INASolver naSolver; naSolver = new NARouteSolver(); INAContextEdit contextEdit = naSolver.CreateContext(deNDS, naSolver.Name) as INAContextEdit; contextEdit.Bind(networkDataset, new GPMessagesClass()); return contextEdit as INAContext; } //得到创建网络分析上下文所需的IDENetworkDataset类型参数 public IDENetworkDataset GetDENetworkDataset(INetworkDataset networkDataset) { //QI from the Network Dataset to the DatasetComponent IDatasetComponent dsComponent; dsComponent = networkDataset as IDatasetComponent; //Get the Data Element return dsComponent.DataElement as IDENetworkDataset; } /// <summary> /// 在内存中创建图层 /// </summary> /// <param name="DataSetName">数据集名称(所建图层名称)</param> /// <param name="AliaseName">别名</param> /// <param name="SpatialRef">空间参考</param> /// <param name="GeometryType">几何类型</param> /// <param name="PropertyFields">属性字段集合</param> /// <returns>IfeatureLayer</returns> public static IFeatureLayer CreateFeatureLayerInmemeory(string DataSetName, string AliaseName, ISpatialReference SpatialRef, esriGeometryType GeometryType, IFields PropertyFields) { IWorkspaceFactory workspaceFactory = new InMemoryWorkspaceFactoryClass(); ESRI.ArcGIS.Geodatabase.IWorkspaceName workspaceName = workspaceFactory.Create("", "MyWorkspace", null, 0); ESRI.ArcGIS.esriSystem.IName name = (IName)workspaceName; ESRI.ArcGIS.Geodatabase.IWorkspace inmemWor = (IWorkspace)name.Open(); IField oField = new FieldClass(); IFields oFields = new FieldsClass(); IFieldsEdit oFieldsEdit = null; IFieldEdit oFieldEdit = null; IFeatureClass oFeatureClass = null; IFeatureLayer oFeatureLayer = null; try { oFieldsEdit = oFields as IFieldsEdit; oFieldEdit = oField as IFieldEdit; for (int i = 0; i < PropertyFields.FieldCount; i++) { oFieldsEdit.AddField(PropertyFields.get_Field(i)); } //IGeometryDef Interface Provides access to members that return information about the geometry definition IGeometryDef geometryDef = new GeometryDefClass(); //IGeometryDefEdit Provides access to members that modify the geometry definition IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef; geometryDefEdit.AvgNumPoints_2 = 5; geometryDefEdit.GeometryType_2 = GeometryType; geometryDefEdit.GridCount_2 = 1; geometryDefEdit.HasM_2 = false; geometryDefEdit.HasZ_2 = false; geometryDefEdit.SpatialReference_2 = SpatialRef; oFieldEdit.Name_2 = "SHAPE"; oFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry; oFieldEdit.GeometryDef_2 = geometryDef; oFieldEdit.IsNullable_2 = true; oFieldEdit.Required_2 = true; oFieldsEdit.AddField(oField); oFeatureClass = (inmemWor as IFeatureWorkspace).CreateFeatureClass(DataSetName, oFields, null, null, esriFeatureType.esriFTSimple, "SHAPE", ""); (oFeatureClass as IDataset).BrowseName = DataSetName; oFeatureLayer = new FeatureLayerClass(); oFeatureLayer.Name = AliaseName; oFeatureLayer.FeatureClass = oFeatureClass; } catch { } finally { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(oField); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFields); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldsEdit); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFieldEdit); System.Runtime.InteropServices.Marshal.ReleaseComObject(name); System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceFactory); System.Runtime.InteropServices.Marshal.ReleaseComObject(workspaceName); System.Runtime.InteropServices.Marshal.ReleaseComObject(inmemWor); System.Runtime.InteropServices.Marshal.ReleaseComObject(oFeatureClass); } catch { } GC.Collect(); } return oFeatureLayer; } //Create fileds public IFields CreateFields() { IFields fields= new FieldsClass(); // create the fields using the required fields method IObjectClassDescription objectClassDescription = new ObjectClassDescriptionClass(); fields = objectClassDescription.RequiredFields; ESRI.ArcGIS.Geodatabase.IFieldsEdit fieldsEdit = (ESRI.ArcGIS.Geodatabase.IFieldsEdit)fields; // Explicit Cast ESRI.ArcGIS.Geodatabase.IField field = new ESRI.ArcGIS.Geodatabase.FieldClass(); // create a user defined text field ESRI.ArcGIS.Geodatabase.IFieldEdit fieldEdit = (ESRI.ArcGIS.Geodatabase.IFieldEdit)field; // Explicit Cast // setup field properties fieldEdit.Name_2 = "SampleField"; fieldEdit.Type_2 = ESRI.ArcGIS.Geodatabase.esriFieldType.esriFieldTypeString; fieldEdit.IsNullable_2 = true; fieldEdit.AliasName_2 = "Sample Field Column"; fieldEdit.DefaultValue_2 = "test"; fieldEdit.Editable_2 = true; fieldEdit.Length_2 = 100; // add field to field collection fieldsEdit.AddField(field); fields = (ESRI.ArcGIS.Geodatabase.IFields)fieldsEdit; // Explicit Cast return fields; //} //return null; } //Get Spatial Reference from Dataset public ISpatialReference GetSpatialReferenceFromDataset(IDataset dataset) { //If the dataset supports IGeoDataset if (dataset is IGeoDataset) { //then grab the spatial reference information and return it. IGeoDataset geoDataset = (IGeoDataset)dataset; return geoDataset.SpatialReference; } else { return null; //otherwise return null } } //在要素类创建要素 public void CreateFeature(IFeatureClass featureClass, IPointCollection PointCollection) { // Ensure the feature class contains points. if (featureClass.ShapeType != esriGeometryType.esriGeometryPoint) { return; } // Build the feature. for (int i = 0; i < PointCollection.PointCount; i++) { IFeature feature = featureClass.CreateFeature(); feature.Shape = PointCollection.get_Point(i); // Apply the appropriate subtype to the feature. ISubtypes subtypes = (ISubtypes)featureClass; IRowSubtypes rowSubtypes = (IRowSubtypes)feature; if (subtypes.HasSubtype) { // In this example, the value of 3 represents the Cross subtype. rowSubtypes.SubtypeCode = 3; } // Initialize any default values the feature has. rowSubtypes.InitDefaultValues(); // Update the value on a string field that indicates who installed the feature. //int contractorFieldIndex = featureClass.FindField("CONTRACTOR"); //feature.set_Value(contractorFieldIndex, "K Johnston"); // Commit the new feature to the geodatabase. feature.Store(); } } //************************************************************ //根据点图层在网络拓扑图层上确定用户要查找最优路径所用经历的点 //************************************************************ public void LoadNANetworkLocations(string strNAClassName, IFeatureClass inputFC, double snapTolerance) { INAClass naClass; INamedSet classes; classes = m_NAContext.NAClasses; 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 (snapTolerance > 0) classLoader.Locator.SnapTolerance = snapTolerance; classLoader.NAClass = naClass; //Create field map to automatically map fields from input class to naclass INAClassFieldMap fieldMap; fieldMap = new NAClassFieldMap(); fieldMap.CreateMapping(naClass.ClassDefinition, inputFC.Fields); classLoader.FieldMap = fieldMap; //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(); } //********************************************************************************* // Set Solver Settings设置阻抗属性等 //********************************************************************************* public void SetSolverSettings() { //Set Route specific Settings INASolver naSolver = m_NAContext.Solver; INARouteSolver cfSolver = naSolver as INARouteSolver; /*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.CreateTraversalResult =true ; cfSolver.UseTimeWindows = false; cfSolver.FindBestSequence = false; cfSolver.PreserveFirstStop = false; cfSolver.PreserveLastStop = false; // Set generic solver settings设置Solver属性,设置路径分析阻抗属性 // 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限制U型转向限制 naSolverSettings.RestrictUTurns = esriNetworkForwardStarBacktrack.esriNFSBNoBacktrack; naSolverSettings.IgnoreInvalidLocations = true; // Set the Hierachy attribute设置层次属性 naSolverSettings.UseHierarchy = chkUseHierarchy.Checked; if (naSolverSettings.UseHierarchy) { naSolverSettings.HierarchyAttributeName = "hierarchy"; naSolverSettings.HierarchyLevelCount = 3; naSolverSettings.set_MaxValueForHierarchy(1, 1); naSolverSettings.set_NumTransitionToHierarchy(1, 9); naSolverSettings.set_MaxValueForHierarchy(2, 2); naSolverSettings.set_NumTransitionToHierarchy(2, 9); } // Do not forget to update the context after you set your impedance naSolver.UpdateContext(m_NAContext, GetDENetworkDataset(m_NAContext.NetworkDataset), new GPMessagesClass()); } //********************************************************************************* // Solve the problem 进行最短路径分析 //********************************************************************************* public string Solve(INAContext naContext, IGPMessages gpMessages) { string errStr = ""; try { //Solving the Problem errStr = "Error when solving"; bool isPartialSolution = naContext.Solver.Solve(naContext, gpMessages, null); if (!isPartialSolution) errStr = "OK"; else errStr = "Partial Solution"; } catch (Exception e) { errStr += " Error Description " + e.Message; } return errStr; } |