Arcengine实现创建网络数据集札记(二)


四 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   }
View Code

     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   }
View Code

      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  
View Code

        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   }
View Code

       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   }
View Code

      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   }
View Code

五 遇到的难题与解决过程

      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”。

 

未完待续......


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM