1. 程式人生 > >C#中GDAL讀寫shp圖層

C#中GDAL讀寫shp圖層

採用GDAL17的C#庫進行shp圖層屬性表讀取和修改操作,C#DLL庫解壓後包含檔案如下:

 

新增引用主要是帶csharp的gdal、ogr、osr三個DLL,程式程式碼如下:

using OSGeo.OGR;

using OSGeo.OSR;

using OSGeo.GDAL;

1.    讀取shp圖層操作

複製程式碼

public void Reforming(string shpFilePath)
{

Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
            Gdal.SetConfigOption("SHAPE_ENCODING", "");
            Ogr.RegisterAll();// 註冊所有的驅動
            DataSource ds = Ogr.Open(shpFilePath, 1);//0表示只讀,1表示可修改  
            if (ds == null) { MessageBox.Show("開啟檔案【{0}】失敗!", shpFilePath); return; }
            // 獲取第一個圖層
            int iLayerCount = ds.GetLayerCount();
            Layer oLayer = ds.GetLayerByIndex(0);
            if (oLayer == null) { MessageBox.Show("獲取第{0}個圖層失敗! n", "0"); return; }
            fieldList = GetFieldList(oLayer);//獲取圖層屬性表字段列表
            int featureCount = oLayer.GetFeatureCount(0);
            //B1.判斷欄位是否存在
            #region shp屬性表
            {
                if (!fieldList.Contains("LL_YAW"))
                {
                    FieldDefn oFieldYaw = new FieldDefn("LL_YAW", FieldType.OFTReal);
                    oFieldYaw.SetWidth(10);
                    oFieldYaw.SetPrecision(8);
                    oLayer.CreateField(oFieldYaw, 1);
                }
                if (!fieldList.Contains("LL_ScaleX"))
                {
                    FieldDefn oFieldYaw = new FieldDefn("LL_ScaleX", FieldType.OFTReal);
                    oFieldYaw.SetWidth(10);
                    oFieldYaw.SetPrecision(8);
                    oLayer.CreateField(oFieldYaw, 1);
                }
                if (!fieldList.Contains("LL_ScaleY"))
                {
                    FieldDefn oFieldYaw = new FieldDefn("LL_ScaleY", FieldType.OFTReal);
                    oFieldYaw.SetWidth(10);
                    oFieldYaw.SetPrecision(8);
                    oLayer.CreateField(oFieldYaw, 1);
                }
            }
            #endregion
              //輸出屬性表字段的詳細資訊,資料型別、寬度、精度等
              FeatureDefn oDefn1 = oLayer.GetLayerDefn();
            int FieldCount1 = oDefn1.GetFieldCount();
            string headerInfo = string.Empty;         
            {
                for (int i = 0; i < FieldCount1; i++)
                {
                    FieldDefn oField = oDefn.GetFieldDefn(i);
                    headerInfo += String.Format("{0}:{1} {2} {3}", oField.GetNameRef(), oField.GetFieldTypeName(oField.GetFieldType()), oField.GetWidth(), oField.GetPrecision());
                    headerInfo += Environment.NewLine;
                }
            }
            MessageBox.Show(headerInfo);


            Feature oFeature = null;
            while ((oFeature = oLayer.GetNextFeature()) != null)
            {
                string name = oFeature.GetFieldAsString(0);
                double x = oFeature.GetFieldAsDouble(1);
                double y = oFeature.GetFieldAsDouble(2);
                double z = oFeature.GetFieldAsDouble(3);                

                //B3.給新增加的欄位賦值
                oFeature.SetField(7, x);
                oFeature.SetField(8, y);
                oFeature.SetField(9, z);
                oLayer.SetFeature(oFeature);//儲存記錄              
            }
            oLayer.Dispose();
            ds.Dispose();//關閉資料集
        }

private List<string> GetFieldList(Layer mLayer)
        {
            List<string> newFieldList = new List<string>();
            FeatureDefn oDefn = mLayer.GetLayerDefn();
            int FieldCount = oDefn.GetFieldCount();
            for (int i = 0; i < FieldCount; i++)
            {
                FieldDefn oField = oDefn.GetFieldDefn(i);
                string fieldName = oField.GetNameRef();
                newFieldList.Add(fieldName);
            }
            return newFieldList;
        }
}

複製程式碼

需要建立或獲取shp圖層的Spatial Reference空間參考座標系WKT時,程式碼如下:

OSGeo.OSR.SpatialReference siref = oLayer.GetSpatialRef();

siref.ExportToWkt(out layerCSWKT);

siref.ImportFromWkt(ref layerCSWKT);

2.建立shp圖層,並將點的座標值寫入屬性表程式碼如下:

複製程式碼

private void button2_Click(object sender, EventArgs e)
        {
            OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");
            // 為了使屬性表字段支援中文,請新增下面這句
            OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "");
            string strVectorFile1 = @"C:\Users\DZY\Desktop\test6";
            Ogr.RegisterAll();

            string strDriver = "ESRI Shapefile";
            Driver oDriver = Ogr.GetDriverByName(strDriver);
            if (oDriver == null)
            {
                MessageBox.Show(" 驅動不可用!\n", strVectorFile1);
                return;
            }
            DataSource ds1 = oDriver.CreateDataSource(strVectorFile1,null);
            if (ds1 == null)
            {
        MessageBox.Show("建立向量檔案【%s】失敗!\n", strVectorFile1);
                return;
            }
            string wkt = "…";//自定義投影座標系的WKT
            OSGeo.OSR.SpatialReference sr = new OSGeo.OSR.SpatialReference(wkt);           
            Layer olayer1 = ds1.CreateLayer("PointLayer",sr,wkbGeometryType.wkbPoint,null);
            //接下來建立屬性表字段
            // 先建立一個叫FieldID的整型屬性
            FieldDefn oFieldID = new FieldDefn("FieldID", FieldType.OFTInteger);
            olayer1.CreateField(oFieldID, 1);

            // 再建立一個叫FeatureName的字元型屬性,字元長度為50
            FieldDefn oFieldName = new FieldDefn("FieldName", FieldType.OFTString);
            oFieldName.SetWidth(50);
            olayer1.CreateField(oFieldName, 1);

            //建立x座標欄位
            FieldDefn oFieldX = new FieldDefn("x", FieldType.OFTReal);
            oFieldX.SetWidth(10);
            oFieldX.SetPrecision(8);
            olayer1.CreateField(oFieldX, 1);
            //建立y座標欄位
            FieldDefn oFieldY = new FieldDefn("y", FieldType.OFTReal);
            oFieldY.SetWidth(10);
            oFieldY.SetPrecision(8);
            olayer1.CreateField(oFieldY, 1);
            //建立z座標欄位
            FieldDefn oFieldZ= new FieldDefn("z", FieldType.OFTReal);
            oFieldZ.SetWidth(10);
            oFieldZ.SetPrecision(8);
            olayer1.CreateField(oFieldZ, 1);
            //寫入第一條資料
            FeatureDefn oDefn = olayer1.GetLayerDefn();
            Feature oFeature = new Feature(oDefn);
            oFeature.SetField(0, 0);
            oFeature.SetField(1, "Point1");
            oFeature.SetField(2, 489592.624);
            oFeature.SetField(3, 3804367.891);
            oFeature.SetField(4, 386.3);
            Geometry geoPoint = new Geometry(OSGeo.OGR.wkbGeometryType.wkbPoint);
            geoPoint.AddPoint(489592.624, 3804367.891, 386.3);
oFeature.SetGeometry(geoPoint);
            olayer1.CreateFeature(oFeature);

            //寫入第二條資料
Feature oFeature1 = new Feature(oDefn);
            oFeature1.SetField(0, 1);
            oFeature1.SetField(1, "Point2");
            oFeature1.SetField(2, 489602.624);
            oFeature1.SetField(3, 3804367.891);
            oFeature1.SetField(4, 389.3);

            geoPoint.AddPoint(489602.624, 3804367.891, 389.3);
            oFeature1.SetGeometry(geoPoint);
            olayer1.CreateFeature(oFeature1);
            oFeature1.Dispose();
            olayer1.Dispose();
            ds1.Dispose();           
            MessageBox.Show("shp圖層建立完成!");
        }

複製程式碼

3.ArcMap中載入效果如下:多個點可採取迴圈遍歷的方式實現。