前回までは、C#でGDAL/OGRを使ってシェープファイルを作図する記事を書いてまいりましたが、今回はシェープファイルの内容(ジオメトリ・属性)を読み取ってみたいと思います。
基本的には、Driver→DataSource→Layer→Feature→Geometryの順番に開いていき、ジオメトリや属性テーブルの内容を読み取っていきます。
早速ですが、サンプルコードを。
using System.IO; using OGR = OSGeo.OGR; using OSR = OSGeo.OSR; /*中略*/ const string sGdalDir = @"C:\Program Files\GDAL"; //GDALのインストールディレクトリ const string sShp = @"D:\hoge\2_poly.shp"; //読み取るシェープファイル const string sCsv = @"D:\hoge\2_poly_ct.csv"; //読み取った結果を書き込むCSV static void Main(string[] args) { #region "OGRの準備(環境変数Pathの設定→Ogr.RegisterAll())" string sVal = Environment.GetEnvironmentVariable("PATH") + ";" + sGdalDir + ";" + Path.Combine(sGdalDir, "csharp") + ";" + Path.Combine(sGdalDir, "gdal-data") + ";" + Path.Combine(sGdalDir, "gdalplugins") + ";" + Path.Combine(sGdalDir, "projlib"); Environment.SetEnvironmentVariable("PATH", sVal); OGR.Ogr.RegisterAll(); #endregion OGR.Driver drv = OGR.Ogr.GetDriverByName("ESRI Shapefile"); //使用するファイルを開く using(StreamWriter sw = new StreamWriter(sCsv, false, Encoding.ASCII)) using (OGR.DataSource ds = drv.Open(sShp, 0)) //SHP:DataSource using (OGR.Layer ly = ds.GetLayerByIndex(0)) //レイヤ { sw.WriteLine("Centroid_X,Centroid_Y,Attribute,GeomNo,PointNo"); //地物をレイヤ先頭の地物にリセットする(?) //参考→ http://www.gdal.org/classOGRLayer.html#aad0f2cd7f0587584b8f382c6a913583c ly.ResetReading(); long lCnt = ly.GetFeatureCount(0); //レイヤ内の地物の数 for (long l = 0; l < lCnt; l++) { OGR.Feature f = ly.GetFeature(l); OGR.Geometry g = f.GetGeometryRef(); //地物に登録されたジオメトリ string sAtt = f.GetFieldAsString("fStr"); //OGR.Geometry gc = g.Centroid(); //コメントを外すと地物の重心を取得(穴の空いたポリゴンの重心をとっているみたい) //sw.WriteLine("{0},{1},{2}", gc.GetX(0), gc.GetY(0), sAtt); for (int i = 0; i < g.GetGeometryCount(); i++) //ジオメトリの中のジオメトリを見ていく { OGR.Geometry gg = g.GetGeometryRef(i); for (int j = 0; j < gg.GetPointCount(); j++) //ジオメトリの構成点を見ていく { sw.WriteLine("{0},{1},{2},{3},{4}", gg.GetX(j), gg.GetY(j), sAtt, i, j); //座標出力 } } } } }
44・45行目がコメントアウトされていますが、ここを外すとポリゴンの重心を出力します。
ポリゴンは穴が空いていますが、穴が空いた状態の重心を出力しているようです。
このコードでは、ポリゴンを構成するリング(閉じた線)の座標をすべて読み取っています。
穴あきポリゴンのため、1つの地物にリングは二つあります。
この二つのリングを識別するためにCSVファイルではGeomNo(サンプルソースの変数名:i)を出力しています。
もとのシェープファイルと、構成点位置・属性を出力したCSVファイルをQGISで図化したのが下図です。ここではGeomNo=0が赤、GeomNo=1が青になっています。
毎度のオマケ:OGR.Ogr.RegisterAll()で「System.TypeInitializationException」が出たときは、構成マネージャーでx68かx64に変更(64bit版GDALを入れていればx64、32bit版ならx86)すると幸せになれるでしょう。