四 ArcEngine实现创建网络数据集
ArcEngine创建网络数据集的过程,与ArcMap设置的过程类似,主要通过六个步骤即可以实现。
1 定义网络数据集对象,并设置基本属性,包括网络数据集名称,空间参考,空间范围等内容。
关键代码如下:
1 ///2 3 /// 创建网络数据集对象 4 5 /// 6 7 /// 包含网络数据集的空间要素集 8 9 /// 网络数据集名称10 11 ///边线网络数据集 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 ///2 3 /// 创建网络源对象 4 5 /// 6 7 /// 参与网络数据集的空间要素类名称 8 9 ///源 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 ///2 3 /// 设置源的连通性,不使用字段值设置 4 5 /// 6 7 /// 源对象 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 ///34 35 /// 设置源对象的方向36 37 /// 38 39 /// 道路属性名40 41 /// 源对象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 ///2 3 /// 网络权重属性设置,多个源参与同一个网络数据集属性的设置 4 5 /// 6 7 /// 参与的所有源对象 8 9 /// 属性名称 10 11 /// 设置表达式 12 13 /// 设置逻辑表达式,可空 14 15 ///16 17 private IEvaluatedNetworkAttribute CreateNetworkSourceAttribute(List 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 ///2 3 /// 指定网络数据集的方向属性 4 5 /// 6 7 /// 网络数据集 8 9 /// 单位类型10 11 /// 创建的长度属性的名称12 13 /// 创建的时间属性名称,可空14 15 /// 创建的道路类型属性名称,可空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 ///2 3 /// 根据网络节点信息,创建网络数据集对象 4 5 /// 6 7 /// 包含网络数据集的空间数据集 8 9 /// 源网络10 11 ///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 /// 40 41 /// 生成网络数据集42 43 /// 44 45 /// 网络数据集46 47 /// 空间数据集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”。
未完待续......