四 ArcEngine实现创建网络数据集
ArcEngine创建网络数据集的过程,与ArcMap设置的过程类似,主要通过六个步骤即可以实现。
1 定义网络数据集对象,并设置基本属性,包括网络数据集名称,空间参考,空间范围等内容。
关键代码如下:
1 /// <summary> 2 3 /// 创建网络数据集对象 4 5 /// </summary> 6 7 /// <param name="featureDataset">包含网络数据集的空间要素集</param> 8 9 /// <param name="NetworkName">网络数据集名称</param> 10 11 /// <returns>边线网络数据集</returns> 12 13 public IDENetworkDataset CreateNetworkDataset(IFeatureDataset featureDataset, string NetworkName) 14 15 { 16 17 if (string.IsNullOrEmpty(NetworkName)||null==featureDataset) 18 19 { 20 21 return null; 22 23 } 24 25 26 27 //定义边线网络数据集对象 28 29 IDENetworkDataset deNetworkDataset = new DENetworkDatasetClass(); 30 31 // 转换为 IGeoDataset 接口 32 33 IGeoDataset geoDataset = (IGeoDataset)featureDataset; 34 35 36 37 // 设置数据集的空间参考和空间范围 38 39 IDEGeoDataset deGeoDataset = (IDEGeoDataset)deNetworkDataset; 40 41 deGeoDataset.Extent = geoDataset.Extent; 42 43 deGeoDataset.SpatialReference = geoDataset.SpatialReference; 44 45 46 47 // 设置名称 48 49 IDataElement dataElement = (IDataElement)deNetworkDataset; 50 51 dataElement.Name = NetworkName; 52 53 // 设置为可创建 54 55 pDENetworkDataset.Buildable = true; 56 57 //设置数据集类型 58 59 pDENetworkDataset.NetworkType = esriNetworkDatasetType.esriNDTGeodatabase; 60 61 62 63 return deNetworkDataset; 64 65 }
2 创建数据源对象;
关键代码如下:
1 /// <summary> 2 3 /// 创建网络源对象 4 5 /// </summary> 6 7 /// <param name="FeatureClassName">参与网络数据集的空间要素类名称</param> 8 9 /// <returns>源</returns> 10 11 public INetworkSource CreateEdgeFeatureNetworkSource(string FeatureClassName) 12 13 { 14 15 16 17 INetworkSource pEdgeNetworkSource = new EdgeFeatureSourceClass(); 18 19 pEdgeNetworkSource.Name = FeatureClassName; 20 21 //设置类型 22 23 pEdgeNetworkSource.ElementType = esriNetworkElementType.esriNETEdge; 24 25 26 27 return pEdgeNetworkSource; 28 29 }
3 设置数据源的属性,主要包括连通性策略,源对象方向;
关键代码如下:
1 /// <summary> 2 3 /// 设置源的连通性,不使用字段值设置 4 5 /// </summary> 6 7 /// <param name="pEdgeNetworkSource">源对象</param> 8 9 public void SetNetworkSourcewithoutSubtypes(INetworkSource pEdgeNetworkSource) 10 11 { 12 13 // 源的连通性 14 15 IEdgeFeatureSource pEdgeFeatureSource = (IEdgeFeatureSource)pEdgeNetworkSource; 16 17 //不使用子类 18 19 pEdgeFeatureSource.UsesSubtypes = false; 20 21 //分组 22 23 pEdgeFeatureSource.ClassConnectivityGroup = 1; 24 25 //使用节点参与 26 27 pEdgeFeatureSource.ClassConnectivityPolicy = esriNetworkEdgeConnectivityPolicy.esriNECPEndVertex; 28 29 } 30 31 32 33 /// <summary> 34 35 /// 设置源对象的方向 36 37 /// </summary> 38 39 /// <param name="StreetFieldName">道路属性名</param> 40 41 /// <param name="EdgeNetworkSource">源对象</param> 42 43 private void SetNetworkSourceDirections(string StreetFieldName, INetworkSource EdgeNetworkSource) 44 45 { 46 47 // 创建道路名字段类对象 48 49 IStreetNameFields streetNameFields = new StreetNameFieldsClass(); 50 51 streetNameFields.Priority = 1; 52 53 // 设置名称 54 55 streetNameFields.StreetNameFieldName = StreetFieldName; 56 57 58 59 //添加到集合中 60 61 IArray nsdArray = new ArrayClass(); 62 63 nsdArray.Add(streetNameFields); 64 65 66 67 //创建网络方向对象 68 69 INetworkSourceDirections nsDirections = new NetworkSourceDirectionsClass(); 70 71 72 73 nsDirections.StreetNameFields = nsdArray; 74 75 76 77 //设置源对象的网络方向 78 79 EdgeNetworkSource.NetworkSourceDirections = nsDirections; 80 81 } 82 83
4 设置网络数据集的属性,对应ArcMap创建网络数据集的第六步设置;
关键代码如下:
1 /// <summary> 2 3 /// 网络权重属性设置,多个源参与同一个网络数据集属性的设置 4 5 /// </summary> 6 7 /// <param name=" SourceLst ">参与的所有源对象</param> 8 9 /// <param name="AttributeName">属性名称</param> 10 11 /// <param name="Expression">设置表达式</param> 12 13 /// <param name="PreLogic">设置逻辑表达式,可空</param> 14 15 /// <returns></returns> 16 17 private IEvaluatedNetworkAttribute CreateNetworkSourceAttribute(List<INetworkSource> SourceLst, string AttributeName, string Expression, string PreLogic) 18 19 { 20 21 //定义变量 22 23 IEvaluatedNetworkAttribute pEvalNetAttr; 24 25 INetworkAttribute2 pNetAttr2; 26 27 INetworkFieldEvaluator pNetFieldEval; 28 29 INetworkConstantEvaluator pNetConstEval; 30 31 32 33 pEvalNetAttr = new EvaluatedNetworkAttributeClass(); 34 35 pNetAttr2 = (INetworkAttribute2)pEvalNetAttr; 36 37 pNetAttr2.Name = AttributeName; 38 39 //计算类型 40 41 pNetAttr2.UsageType = esriNetworkAttributeUsageType.esriNAUTCost; 42 43 //数值类型 44 45 pNetAttr2.DataType = esriNetworkAttributeDataType.esriNADTDouble; 46 47 //单位类型 48 49 pNetAttr2.Units = esriNetworkAttributeUnits.esriNAUMeters; 50 51 pNetAttr2.UseByDefault = true; 52 53 54 55 //计算表达式 56 57 pNetFieldEval = new NetworkFieldEvaluatorClass(); 58 59 pNetFieldEval.SetExpression(Expression, PreLogic); 60 61 62 63 //参与的每个源的计算表达式设置 64 65 SourceLst.ForEach(pEdgeNetworkSource => 66 67 { 68 69 //正向计算表达式 70 71 pEvalNetAttr.set_Evaluator(pEdgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)pNetFieldEval); 72 73 //反向计算表达式 74 75 pEvalNetAttr.set_Evaluator(pEdgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)pNetFieldEval); 76 77 78 79 }); 80 81 82 83 pNetConstEval = new NetworkConstantEvaluatorClass(); 84 85 pNetConstEval.ConstantValue = 0; 86 87 88 89 //设置边,交汇点,转弯的默认值为常数 90 91 pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETEdge, 92 93 (INetworkEvaluator)pNetConstEval); 94 95 pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETJunction, 96 97 (INetworkEvaluator)pNetConstEval); 98 99 pEvalNetAttr.set_DefaultEvaluator(esriNetworkElementType.esriNETTurn, 100 101 (INetworkEvaluator)pNetConstEval); 102 103 104 105 return pEvalNetAttr; 106 107 }
5 设置网络数据集的方向;
关键代码如下:
1 /// <summary> 2 3 /// 指定网络数据集的方向属性 4 5 /// </summary> 6 7 /// <param name="deNetworkDataset">网络数据集</param> 8 9 /// <param name="UnitsType">单位类型</param> 10 11 /// <param name="LengthAttribute"> 创建的长度属性的名称</param> 12 13 /// <param name="TimeAttribute"> 创建的时间属性名称,可空</param> 14 15 /// <param name="RoadClassAttribute">创建的道路类型属性名称,可空</param> 16 17 public void SetNetworkDirction(IDENetworkDataset deNetworkDataset,esriNetworkAttributeUnits UnitsType, string LengthAttribute, string TimeAttribute, string RoadClassAttribute) 18 19 { 20 21 // 创建网络方向对象 22 23 INetworkDirections networkDirections = new NetworkDirectionsClass(); 24 25 networkDirections.DefaultOutputLengthUnits = UnitsType; 26 27 28 29 //设置长度属性 30 31 if (!string.IsNullOrEmpty(LengthAttribute)) 32 33 { 34 35 networkDirections.LengthAttributeName = LengthAttribute; 36 37 } 38 39 //设置时间属性 40 41 if (!string.IsNullOrEmpty(TimeAttribute)) 42 43 { 44 45 networkDirections.TimeAttributeName = TimeAttribute; 46 47 } 48 49 //设置道路类型属性 50 51 if (!string.IsNullOrEmpty(RoadClassAttribute)) 52 53 { 54 55 networkDirections.RoadClassAttributeName = RoadClassAttribute; 56 57 } 58 59 60 61 // 设置网络数据集的方向属性 62 63 deNetworkDataset.Directions = networkDirections; 64 65 }
6 建立网络数据集;
关键代码如下:
1 /// <summary> 2 3 /// 根据网络节点信息,创建网络数据集对象 4 5 /// </summary> 6 7 /// <param name="_pFeatureDataset">包含网络数据集的空间数据集</param> 8 9 /// <param name="_pDENetDataset">源网络</param> 10 11 /// <returns></returns> 12 13 public INetworkDataset CreateBuildingDataset(IFeatureDataset _pFeatureDataset, IDENetworkDataset2 _pDENetDataset) 14 15 { 16 17 IFeatureDatasetExtensionContainer pFeatureDatasetExtensionContainer = (IFeatureDatasetExtensionContainer)_pFeatureDataset; 18 19 IFeatureDatasetExtension pFeatureDatasetExtension = pFeatureDatasetExtensionContainer.FindExtension(esriDatasetType.esriDTNetworkDataset); 20 21 IDatasetContainer2 pDatasetContainer2 = (IDatasetContainer2)pFeatureDatasetExtension; 22 23 IDEDataset pDENetDataset = (IDEDataset)_pDENetDataset; 24 25 26 27 //创建网络数据集 28 29 INetworkDataset pNetworkDataset = (INetworkDataset)pDatasetContainer2.CreateDataset(pDENetDataset); 30 31 32 33 return pNetworkDataset; 34 35 } 36 37 38 39 /// <summary> 40 41 /// 生成网络数据集 42 43 /// </summary> 44 45 /// <param name="networkDataset">网络数据集</param> 46 47 /// <param name="geoDataset">空间数据集</param> 48 49 public bool BuildNetwork(INetworkDataset networkDataset, featureDataset) 50 51 { 52 53 // 空间数据集转换为IGeoDataset 接口 54 55 IGeoDataset geoDataset = (IGeoDataset)featureDataset; 56 57 58 59 if (null==geoDataset) 60 61 { 62 63 return false; 64 65 } 66 67 68 69 INetworkBuild networkBuild = (INetworkBuild)networkDataset; 70 71 //构建网络数据集 72 73 networkBuild.BuildNetwork(geoDataset.Extent); 74 75 76 77 return true; 78 79 }
五 遇到的难题与解决过程
ArcEngine创建网络数据集过程中,遇到一些问题,主要是两部分原因,一是扩展许可问题,二是属性值设置的问题。
1 扩展许可问题:
项目开发过程中,注意到了许可初始化的问题,通过代码实现ArcEngine许可初始化。但是,在IDatasetContainer2接口执行CreateDataset方法时,报错"异常来自HRESULT:0x80040220”。
该异常产生的原因是,由于网络数据集创建功能接口的实现,需要ArcEngine扩展许可初始化,即调用IAoInitialize 接口的CheckOutExtension方法,注册空间分析的扩展许可。
2 属性值设置问题:
1)官网的样例代码对于创建网络数据集属性接口IEvaluatedNetworkAttribute时,都是针对当个参与源对象INetworkSource进行设置的。如果多个源对象参与设置同一个IEvaluatedNetworkAttribute接口设置时,需要遍历每个源对象进行设置。
关键代码段如下:
//参与的每个源的计算表达式设置
SourceLst.ForEach(pEdgeNetworkSource =>
{
//正向计算表达式
pEvalNetAttr.set_Evaluator(pEdgeNetworkSource, esriNetworkEdgeDirection.esriNEDAlongDigitized, (INetworkEvaluator)pNetFieldEval);
//反向计算表达式
pEvalNetAttr.set_Evaluator(pEdgeNetworkSource, esriNetworkEdgeDirection.esriNEDAgainstDigitized, (INetworkEvaluator)pNetFieldEval);
});
2)创建的网络数据集属性IEvaluatedNetworkAttribute,是用在设置网络数据集的方向属性,需要保证名称一致。
例如,定义了名称为“Length”的IEvaluatedNetworkAttribute对象,在设置网络数据集的长度属性为该定义的对象时,需要把INetworkDirections接口的LengthAttributeName属性设置为“Length”。这样,网络数据集在计算长度属性时,根据已定义的接口计算。否则,会报错“The network attribute name is invalid”。
未完待续......