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