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

    未完待续......

  • 相关阅读:
    ionic3使用@angular/http 访问nodejs(koa2框架)服务不能返回数据
    FacebookFriendAdderPro
    SEO记录-1
    thanos 实现 prometheus 高可用 数据持久化2
    Prometheus + consul + grafana 监控体系搭建1
    解决问题方法
    原则设定
    docker-基本概念、架构和使用
    如何有效学习
    社会~
  • 原文地址:https://www.cnblogs.com/chuzhouGIS/p/3576176.html
Copyright © 2020-2023  润新知