基於C#的ArcEngine二次開發21:線(面)要素折角監測、折點提取與shape文件導出

在要素檢查中,我們經常遇到線段打折的情形,本文要解決的就是如何和快速監測出這些折角;主要內容包含如下內容:

  1. 計算相鄰三點的夾角公式
  2. 從線狀要素中獲取其折點座標
  3. 由折點座標,逐點判定是否有不滿足閾值要求的折角出現,如有則輸出記錄

目錄

 

目錄

1. 計算兩個向量之間的夾角

1.1 基礎數學理論:

1.2 代碼實現

1.3 測試代碼

2. 對數據集中的線要素進行檢測

2.1 逐點檢查

2.2 調用執行

2.3 結果展示

3 ArcGIS提取線要素的折點座標並顯示的方法

3.1 要素折點轉點

3.2 AE+C# 代碼獲取線要素的折點座標集

3.3 測試結果:

3.4 面要素折角

3.5 改進版本

4 將結果導出爲shp文件

4.1 點集導出爲shape文件的自定義函數

4.2 參考材料

4.2.1 思路

4.2.2 必要元素

4.2.2 代碼說明

 


1. 計算兩個向量之間的夾角

1.1 基礎數學理論:

1.2 代碼實現

權限許可與環境搭建參見博文:

C#編程學習10:ArcGIS、ArcEngine安裝簡要教程及C#程序創建

可能用到名稱空間:

using ESRI.ArcGIS.Carto;
using System.Data.OleDb;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.DataManagementTools;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Geodatabase;

反餘弦曲線

引子:兩種shape文件數據庫操作的方法

  • 通過FeatureLayer 找到數據庫
IfeatureClass featClass = featureLayer.FeatureClass;
IDataSet dataset = featClass as IDataset;
IWorkspace ws = dataset.Workspace;
  • 通過數據庫文件讀取數據
IWorkspaceFactory wsf = new ShapefileWorkspaceFactory();
IWorkspace  pWorkspace = wsf.Open(filePath, 0) ;//filePath爲shapefile所在的文件夾
IFeatureWorkspace pFeatureWorkspace = pWorkspace ;
IFeatureClass pFeatureClass  = pFeatureWorkspace.OpenFeatureClass("parcels");//parcels爲shapefile文件名pacels.shp

兩個重載版本:

  • 基於IPoint接口的版本
  • 基於System.Drawing.PointF的版本
        /// <summary>
        /// 計算連續三點構成的兩個向量的夾角
        /// </summary>
        /// <param name="pt1">起點1</param>
        /// <param name="pt2">連接點2</param>
        /// <param name="pt3">終點3</param>
        /// <returns>向量夾角</returns>
        public double calAngleVectors(IPoint pt1, IPoint pt2, IPoint pt3)
        {
            IPoint vec1 = new ESRI.ArcGIS.Geometry.Point();
            vec1.X = pt2.X - pt1.X;
            vec1.Y = pt2.Y - pt1.Y;
                      
            IPoint vec2 = new ESRI.ArcGIS.Geometry.Point();
            vec2.X = pt3.X - pt2.X;
            vec2.Y = pt3.Y - pt2.Y;

            double len1 = Math.Sqrt(vec1.X * vec1.X + vec1.Y * vec1.Y);
            double len2 = Math.Sqrt(vec2.X * vec2.X + vec2.Y * vec2.Y);
            double v12 = vec1.X*vec2.X + vec1.Y*vec2.Y;
            double cos = v12 / (len1 * len2);
            return Math.Acos(cos) * 180 / Math.PI;         
        }


         /// <summary>
        /// 計算連續三點構成的兩個向量的夾角
        /// </summary>
        /// <param name="pt1">起點1</param>
        /// <param name="pt2">連接點2</param>
        /// <param name="pt3">終點3</param>
        /// <returns>向量夾角</returns>
        public double calAngleVectors(System.Drawing.PointF pt1, System.Drawing.PointF pt2, System.Drawing.PointF pt3)
        {
            System.Drawing.PointF vec1 = new System.Drawing.PointF();
            vec1.X = pt2.X - pt1.X;
            vec1.Y = pt2.Y - pt1.Y;

            System.Drawing.PointF vec2 = new System.Drawing.PointF();
            vec2.X = pt3.X - pt2.X;
            vec2.Y = pt3.Y - pt2.Y;

            double len1 = Math.Sqrt(vec1.X * vec1.X + vec1.Y * vec1.Y);
            double len2 = Math.Sqrt(vec2.X * vec2.X + vec2.Y * vec2.Y);
            double v12 = vec1.X * vec2.X + vec1.Y * vec2.Y;
            double cos = v12 / (len1 * len2);
            double arc = Math.Acos(cos);
            return Math.Acos(cos) * 180 / Math.PI;
        }

1.3 測試代碼

float tmp = (float)(Math.Sqrt(3.0));
double re = calAngleVectors(new PointF(1-tmp,0), new PointF(1,1), new PointF(0,0));
//連續三個點座標爲(1-sqrt(3), 0), (1,1), (0,0),構成夾角爲15度

2. 對數據集中的線要素進行檢測

步驟如下:

  • 獲取要處理的數據庫、線要素層
  • 線要素層節點提取
  • 逐三點監測其夾角是否滿足閾值
  • 小於規定閾值的,將其中點座標加入到監測列表中

2.1 逐點檢查

注意:折角的cos值爲負,如果你要檢查小於15度的折角,判斷條件應爲180-15=165

第二個參數dsPath不要也行

        /// <summary>
        /// 檢測當前線層是否包含小於指定閾值的折角
        /// </summary>
        /// <param name="wsPath">工作空間路徑</param>
        /// <param name="dsPath">數據集路徑</param>
        /// <param name="feaPath">要素層名稱</param>
        /// <param name="angleLimit">折角界限</param>  
        /// <returns>夾角在指定閾值內的點集</returns>
        public List<IPoint> checkAngle(string wsPath, string dsPath, string feaPath, double angleLimit)
        {
            //1. 打開工作空間
            // Open the workspace and the required datasets.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
            //ESRI.ArcGIS.DataSourcesGDB
            IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();

            IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
            //2. 打開數據集,這一步可以省略不要,這樣就不用傳遞第二個參數了
            IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath);
            //3. 打開要素層
            IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(feaPath);
            //4. 查詢所有要素
            string where = "";
            IQueryFilter filter = new QueryFilterClass();
            filter.WhereClause = where;
            //5.定義查詢遊標並循環迭代
            IFeatureCursor pFeatcursor = pFeaterClass.Search(filter, false);
            IFeature pFeature = pFeatcursor.NextFeature();
            //6. 運算結果存儲
            
            List<IPoint> liPts = new List<IPoint>();
            //7. 循環遍歷
            while (pFeature != null)
            {
                int cnt = pFeature.Fields.FieldCount;
                esriFeatureType type = pFeature.FeatureType;//獲取要素的類型
                IPointCollection pPc = pFeature.Shape as IPointCollection;
                int ptCnt = pPc.PointCount;//獲取當前要素中的點數
                //7.1 跳過沒有折點的線段
                if (ptCnt >= 2)
                {
                    string coors = string.Empty;
                    for (int i = 0; i < ptCnt - 2; i++)
                    {
                        double angle = calAngleVectors(pPc.Point[i], pPc.Point[i + 1], pPc.Point[i + 2]);
                        if (angle >= (180 - angleLimit))
                        {
                            liPts.Add(pPc.Point[i+1]);
                            //sw.WriteLine(pPc.Point[i + 1].X.ToString() + "," + pPc.Point[i + 1].Y.ToString());
                        }
                        //獲取線要素所有折點座標並顯示
                        //coors += pPc.Point[i].X +", "+ pPc.Point[i].Y + "\n";
                        //coors += angle.ToString() + "\n";
                    }
                    //MessageBox.Show(coors, "當前要素的節點座標集合");
                }
                //將遊標移動到下一個要素
                pFeature = pFeatcursor.NextFeature();
            }

            return liPts;
        }

2.2 調用執行

 private void buttonExecute_Click(object sender, EventArgs e)
        {
            try
            {
                    string inPath = textBoxInput.Text;
                    string ouPath = textBoxOutput.Text;
                    if (System.IO.File.Exists(inPath) && System.IO.Path.GetFileName(ouPath) != "")
                    {
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(ouPath);
                        List<IPoint> pts = checkAngle(inPath, "Topology", "LRDL", 15);
                        foreach (IPoint pt in pts)
                        {
                            sw.WriteLine(pt.X.ToString() + ", "  + pt.Y.ToString());
                        }
                        sw.Close();
                        sw.Dispose();
                    }
                    MessageBox.Show("折角檢查完畢", "完成提示");
            }
            catch (Exception ex)
            {
                MessageBox.Show("觸發異常操作:" + ex.ToString(), "執行失敗");
            }           
        }

2.3 結果展示

步驟:

  • 添加導出的txt數據
  • 右鍵,顯示XY數據

     

小於閾值的折點被顯示出來,之後右鍵-->數據-->導出數據,輸出爲shp要素類

 

 

3 ArcGIS提取線要素的折點座標並顯示的方法

3.1 要素折點轉點

ArcToolBox --> 數據管理工具 --> 要素 --> 要素折點轉點

拖入要轉點的要素,確定

添加xy座標,將剛纔轉的要素層拖入,確定

打開屬性表,即可看到折點座標:

3.2 AE+C# 代碼獲取線要素的折點座標集

        /// <summary>
        /// 獲取當前線層所有折點座標
        /// </summary>
        /// <param name="wsPath">工作空間路徑</param>
        /// <param name="dsPath">數據集路徑</param>
        /// <param name="feaPath">要素層名稱</param> 
        /// <returns>折點集</returns>
        public List<IPoint> getAllPointFromLine(string wsPath, string dsPath, string feaPath)
        {
            //1. 打開工作空間
            // Open the workspace and the required datasets.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
            //ESRI.ArcGIS.DataSourcesGDB
            IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();

            IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
            //2. 打開數據集
            IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath);
            //3. 打開要素層
            IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(feaPath);
            //4. 查詢所有要素
            string where = "";
            IQueryFilter filter = new QueryFilterClass();
            filter.WhereClause = where;
            //5.定義查詢遊標並循環迭代
            IFeatureCursor pFeatcursor = pFeaterClass.Search(filter, false);
            IFeature pFeature = pFeatcursor.NextFeature();
            //6. 運算結果存儲
            
            List<IPoint> liPts = new List<IPoint>();
            //7. 循環遍歷
            while (pFeature != null)
            {
                int cnt = pFeature.Fields.FieldCount;
                esriFeatureType type = pFeature.FeatureType;//獲取要素的類型
                IPointCollection pPc = pFeature.Shape as IPointCollection;
                int ptCnt = pPc.PointCount;//獲取當前要素中的點數
                string coors = string.Empty;
                for (int i = 0; i < ptCnt; i++)
                {
                     liPts.Add(pPc.Point[i]);
                }
                //將遊標移動到下一個要素
                pFeature = pFeatcursor.NextFeature();
            }
            return liPts;
        }

測試代碼:

private void buttonExecute_Click(object sender, EventArgs e)
        {
            try
            {
                    string inPath = textBoxInput.Text;
                    string ouPath = textBoxOutput.Text;
                    if (System.IO.File.Exists(inPath) && System.IO.Path.GetFileName(ouPath) != "")
                    {
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(ouPath);
                        List<IPoint> pts = getAllPointFromLine(inPath, "Topology", "LRDL");
                        foreach (IPoint pt in pts)
                        {
                            sw.WriteLine(pt.X.ToString() + ", "  + pt.Y.ToString());
                        }
                        sw.Close();
                        sw.Dispose();
                    }
                    MessageBox.Show("折角檢查完畢", "完成提示");
            }
            catch (Exception ex)
            {
                MessageBox.Show("觸發異常操作:" + ex.ToString(), "執行失敗");
            }
        }

3.3 測試結果:

3.4 面要素折角

面折角監測與線折角監測的區別:

  • 線要素是開放的,面要素的是封閉的
  • 提取的線要素點集,個數等於線要素包含的實際節點數
  • 提取的面要素的點集,個數爲面要素節點數目+1;也就是說,面要素的第一個點算了兩次;我們在進行面折角檢查時,由於我們選擇的是連續的三個節點,因此需要把第二個點再加入進行計算

如下圖,提取的面要素的點集提取的0,1,2,3,4,5;其中的5和0是同一個點;現在我們要將點集改成0,1,2,3,4,5,1,也就是把倒數第二個點加到最後。

        /// <summary>
        /// 檢測當前線層是否包含小於指定閾值的折角
        /// </summary>
        /// <param name="wsPath">工作空間路徑</param>
        /// <param name="feaPath">要素層名稱</param>
        /// <param name="angleLimit">折角界限</param>  
        /// <returns>夾角在指定閾值內的點集</returns>
        public List<IPoint> checkAngle(string wsPath, string feaPath, double angleLimit)
        {
            //1. 打開工作空間
            // Open the workspace and the required datasets.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
            //ESRI.ArcGIS.DataSourcesGDB
            IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();

            IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
            
            //2. 打開數據集
            //IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath);
            //3. 打開要素層
            IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(feaPath);
            //4. 查詢所有要素
            string where = "";
            IQueryFilter filter = new QueryFilterClass();
            filter.WhereClause = where;
            //5.定義查詢遊標並循環迭代
            IFeatureCursor pFeatcursor = pFeaterClass.Search(filter, false);
            IFeature pFeature = pFeatcursor.NextFeature();
            //6. 運算結果存儲

            List<IPoint> liPts = new List<IPoint>();
            //7. 循環遍歷
            while (pFeature != null)
            {
                int cnt = pFeature.Fields.FieldCount;
                esriFeatureType type = pFeature.FeatureType;//獲取要素的類型
                IPointCollection pPc = pFeature.Shape as IPointCollection;
                
                //獲取幾何要素的類型
                //注意,由於面狀要素是封閉的,故得到的點集中第一個點座標和最後一個點座標是一樣的
                //在面折角檢查時,需要檢查時在需要在提取點集的最後位置添加點集中的第二個點
                esriGeometryType geoType = pFeature.Shape.GeometryType;
                if (geoType == esriGeometryType.esriGeometryPolygon)
                {
                    //面是封閉的,因此將第二個點加入加進去參與計算
                    pPc.AddPoint(pPc.Point[1]);
                }
                
                int ptCnt = pPc.PointCount;//獲取當前要素中的點數
                
                //7.1 跳過只有起點和終點的線段
                if (ptCnt >= 2)
                {
                    //string coors = string.Empty;
                    for (int i = 0; i < ptCnt - 2; i++)
                    {
                        double angle = calAngleVectors(pPc.Point[i], pPc.Point[i + 1], pPc.Point[i + 2]);
                        if (angle >= (180 - angleLimit))
                        {
                            liPts.Add(pPc.Point[i + 1]);
                        }
                    }
                }                                       
                //將遊標移動到下一個要素
                pFeature = pFeatcursor.NextFeature();
            }
            return liPts;
        }

3.5 改進版本

對於面中包含房屋等漏洞的情形,可能存在內外邊界銜接點處計算出本不必要的面折角

因此需要對面的折角識別進行必要的拆分,即先提取出構成面幾何圖形,然後逐個幾何圖形進行檢查

此部分代碼參見文末公衆號:

4 將結果導出爲shp文件

注意事項:

  1. 在給定的結果目錄下指定工作空間
  2. 設置shape文件的字段集合,包括幾何類型、座標系統、以及自己定義的字段
  3. 字段值的設置
  4. 圖形賦值,即將點要素賦值給shape文件的要素當中

4.1 點集導出爲shape文件的自定義函數

本函數獲取投影座標的操作比較蹩腳,若以後找到更好的辦法,在進行修改

        /// <summary>
        /// 將點集導出爲shp文件
        /// </summary>
        /// <param name="inPath">輸入數據集</param>
        /// <param name="liPts">要導出的點集</param>
        /// <param name="checkLayerName">點集的來源圖層</param>
        /// <param name="ouPath">導出的shape文件的結果保存路徑</param>
        public void ExportPtsToShapefile(string inPath, List<IPoint> liPts, string checkLayerName, string ouPath)
         {
             //1. 打開工作空間
             string strShapeFolder = System.IO.Path.GetDirectoryName(ouPath);
             const string strShapeFieldName = "shape";
             IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass();
             IFeatureWorkspace pWS = (IFeatureWorkspace)pWSF.OpenFromFile(strShapeFolder,0);
             //2. 設置字段集
             IFields pFields = new FieldsClass();
             IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields;

             //3. 設置字段
             IField pField = new FieldClass();
             IFieldEdit pFieldEdit = (IFieldEdit)pField;
             //4. 創建類型爲幾何類型的字段
             pFieldEdit.Name_2 = strShapeFieldName;
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
             //爲esriFieldTypeGeometry類型的字段創建幾何定義,包括類型和空間參照
             IGeometryDef pGeoDef = new GeometryDefClass(); //The geometry definition for the field if IsGeometry is TRUE.
             IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef;

             //4.1 將原始數據的投影信息賦值給新的檢查結果圖層
             IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();
             IWorkspace workspace = workspaceFactory.OpenFromFile(inPath, 0);
             IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
             IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(checkLayerName);//這個地方可以繼續研究如何更簡便的獲取工作空間的座標系統
             IGeoDataset geoDatabase = pFeaterClass as IGeoDataset;
             //設置座標系統
             IProjectedCoordinateSystem tProjectedCoordinateSystem = geoDatabase.SpatialReference as IProjectedCoordinateSystem;
             pGeoDefEdit.SpatialReference_2 = tProjectedCoordinateSystem;   
             pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;          
             pFieldEdit.GeometryDef_2 = pGeoDef;
             pFieldsEdit.AddField(pField);

             //添加其他的字段
             pField = new FieldClass();
             pFieldEdit = (IFieldEdit)pField;
             pFieldEdit.Name_2 = "X";
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
             //pFieldEdit.Precision_2 = 7;//數值精度
             //pFieldEdit.Scale_2 = 6;//小數點位數
             pFieldsEdit.AddField(pField);

             pField = new FieldClass();
             pFieldEdit = (IFieldEdit)pField;
             pFieldEdit.Name_2 = "Y";
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
             //pFieldEdit.Precision_2 = 7;//數值精度
             //pFieldEdit.Scale_2 = 6;//小數點位數
             pFieldsEdit.AddField(pField);

             //創建shapefile
             string strShapeName = System.IO.Path.GetFileName(ouPath);           
             IFeatureClass shpFeatureClass = pWS.CreateFeatureClass(strShapeName, pFields, null, null, esriFeatureType.esriFTSimple, strShapeFieldName, "");

             //5. 向shape中添加要素
             IPoint pPoint = new PointClass();
             foreach (IPoint pt in liPts)
             {
                 IFeature pFeature = shpFeatureClass.CreateFeature();
                 //5.1 將點座標設置到屬性表中

                 //獲取字段,並對字段值進行屬性賦值
                 IFields fields = pFeature.Fields;//獲取該對象的字段
                 int xIdx = fields.FindFieldByAliasName("X");
                 pFeature.set_Value(xIdx, pt.X);
                 int yIdx = fields.FindFieldByAliasName("Y");
                 pFeature.set_Value(yIdx, pt.Y);

                 //5.2 將點設置爲shp文件的圖形要素
                 pFeature.Shape = pt;//這一句十分重要,不然點顯示不出來
                 //如果導出的其他類型的元素(IPolygon,IPolyline)
                 pFeature.Store();
             }                               
         }

測試函數的修改:

        private void buttonExecute_Click(object sender, EventArgs e)
        {
            try
            {
                //---------------------------檢查小於15度角的代碼------------------------------------
                string inPath = textBoxInput.Text;
                string ouPath = textBoxOutput.Text;
                if (System.IO.File.Exists(inPath) && System.IO.Path.GetFileName(ouPath) != "")
                {
                    //string extend = System.IO.Path.GetExtension(ouPath);
                    if (System.IO.Path.GetExtension(ouPath) == ".txt")
                    {
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(ouPath);
                        List<IPoint> pts = checkAngle(inPath, "Topology", "LRDL", 15);
                        //List<IPoint> pts = getAllPointFromLine(inPath, "Topology", "LRDL");
                        foreach (IPoint pt in pts)
                        {
                            sw.WriteLine(pt.X.ToString() + ", " + pt.Y.ToString());
                        }
                        sw.Close();
                        sw.Dispose();
                    }
                    else
                    {
                        List<IPoint> pts = checkAngle(inPath, "Topology", "LRDL", 15);
                        ExportPtsToShapefile(inPath, pts, "LRDL", ouPath);
                    }                 
                }
                MessageBox.Show("折角檢查完畢", "完成提示");
                //------------------------------------------------------------------------             
            }
            catch (Exception ex)
            {
                MessageBox.Show("觸發異常操作:" + ex.ToString(), "執行失敗");
            }
        }

4.2 參考材料

原文地址:

4.2.1 思路

根據點座標創建Shapefile文件大致思路是這樣的:
(1)創建表的工作空間,通過 IField、IFieldsEdit、IField 等接口創建屬性字段,添加到要素集中。
(2)根據獲取點的座標信息爲屬性字段賦值,進而得到圖層的要素集

4.2.2 必要元素

將創建 Shapefile 文件代碼封裝成方法如下,這裏說明一下創建一 個 Shapefile 文件至少需要配置的元素:

  • 首先,當我們創建一個shp文件時,ArcMap會自動生成如下字段:

這裏寫圖片描述

其中shp表示幾何字段,我們需要設置 IFile.Name 和 IField.Type 來定義這個字段

  • 如果我們沒有設置空間座標時,會彈出如下對話框:

這裏寫圖片描述

因此第二步我們需要設置shp文件的空間座標。 這裏是通過設置 IField.GeometryDef 實現的。這個屬性其實是IGeometryDef接口,通過對這個接口的 GeometryType 和 SpatialReference 屬性進行設置即可完成對空間座標的定義。

4.2.2 代碼說明

封裝的這段代碼裏,發現對於 IFeature 和 IFeatureClass 還是不怎麼理解,通過查閱資料發現, IFeature 繼承自 IRow 和 IObject ,由於IFeature 可以通過 IFeatureClass 創建而成,因此可以知道的是IFeatureClass 是和ITable處於同一個級別,IFeature 相當於是屬性表中的一行。
 

注:此代碼未做驗證,目測正確,僅共學習參考

private IFeatureLayer CreateShpFromPoints(List<CPoint> cPointList,string filePath)
{
    //其中,CPoint爲存儲點數據的結構體,包含name,x,y屬性
    //利用IWorkspaceFactory打開工作空間
    int index = filePath.LastIndexOf('\\');
    string folder = filePath.Substring(0, index);
    string shapeName = filePath.Substring(index + 1);  
    IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass();
    IFeatureWorkspace pFWS = (IFeatureWorkspace)pWSF.OpenFromFile(folder, 0);

    //創建字段編輯所需要的接口
    IFields pFields = new FieldsClass();
    IFieldsEdit pFieldsEdit;
    pFieldsEdit = (IFieldsEdit)pFields;

    //給字段屬性、類型賦值
    IField pField = new FieldClass();
    IFieldEdit pFieldEdit = (IFieldEdit)pField;
    pFieldEdit.Name_2 = "Shape";
    pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
    IGeometryDef pGeometryDef = new GeometryDefClass();
    IGeometryDefEdit pGDefEdit = (IGeometryDefEdit)pGeometryDef;
    pGDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
    //定義座標系
    ISpatialReferenceFactory pSRF = new SpatialReferenceEnvironmentClass();
    ISpatialReference pSpatialReference = pSRF.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_Beijing1954);
    pGDefEdit.SpatialReference_2 = pSpatialReference;

    pFieldEdit.GeometryDef_2 = pGeometryDef;
    pFieldsEdit.AddField(pField);

    IFeatureClass pFeatureClass;
    pFeatureClass = pFWS.CreateFeatureClass(shapeName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");

     IPoint pPoint = new PointClass();
     for (int j = 0; j < cPointList.Count; j++)
     {
         pPoint.X = cPointList[j].X;
         pPoint.Y = cPointList[j].Y;

         IFeature pFeature = pFeatureClass.CreateFeature();
         pFeature.Shape = pPoint;
         pFeature.Store();
     }

     IFeatureLayer pFeatureLayer = new FeatureLayerClass();
     pFeatureLayer.Name = shapeName;
     pFeatureLayer.FeatureClass = pFeatureClass;
     return pFeatureLayer;
}

 


喜歡作者可以關注個人公衆號,純屬愛好,不定時更新;

關於代碼的改進請關注【運籌優化與圖像處理算法編程】公衆號《ArcEngine實現線(面)折角監測》

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章