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

 

未完待续......

你可能感兴趣的:(ArcEngine)