前回までは、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)すると幸せになれるでしょう。

