[DotSpatial]ポイントがポリゴンに含まれているか判別する

多数の地点が市町村などの領域に含まれているか否かを判別したい用事があったので、DotSpatialを使って判別してみました。DotSpatialではいくつかの手法で判別することができるようなので、3手法ほど試して見ました。手法としては、Topology名前空間のPolygonクラスを使う方法(下記1と2)と、Data名前空間のFeatureクラスを使う方法があるようです。また、使うメソッドは1がContainsなのに対して、2・3は使うクラス(名前空間も)が違うのにIsWithinDistanceを使う点では共通しています。

  1. Topology.Polygon.Contains(Point)
  2. Topology.Polygon.IsWithinDistance(Point, double)
  3. Data.Feature.IsWithinDistance(Feature, double)

なお、Containsメソッドは単に点が中に含まれているかだけを判別するのに対して、IsWithinDistanceは中に含まれていなくても第二引数入力された距離以内であればTrueを返すようです。

ということで、↓のようにポイント(1~7)がポリゴン(A~C)に含まれているかを判別してみます。

キャプチャ

早速、サンプルコードです

//これが書いてある前提
using System.IO;
using DotSpatial.Data;
using DotSpatial.Topology;

/* 中略 */

const string sPolygon = @"C:\hoge\Polygon.shp"; //ポリゴン
const string sPoint = @"C:\hoge\Point.shp"; //ポイント
const string sOut = @"C:\hoge\Result.txt"; //結果を出力するテキストファイル

//シェープファイルを開く・準備する
using(PolygonShapefile psPoly = new PolygonShapefile(sPolygon))
using(PointShapefile psPt = new PointShapefile(sPoint))
using(StreamWriter sw = new StreamWriter(sOut, false, Encoding.UTF8))
{
    foreach (Feature fPoly in psPoly.Features)
    {
    	//DotSpatial.Topology.PolygonをDotSpatial.Data.Featureから生成
        Polygon pg = new Polygon(fPoly.Coordinates);
        foreach (Feature fPt in psPt.Features)
        {
            //DotSpatial.Topology.PointをDotSpatial.Data.Featureから生成
            Point pt = new Point(fPt.Coordinates[0]);

            //判別方法①
            //DotSpatial.Topology.Polygon.Contains(Point)
            sw.WriteLine("Method1 Polygon:{0} Point:{1} →{2}",
                fPoly.DataRow[0].ToString(), 
                fPt.DataRow[0].ToString(),
                pg.Contains(pt).ToString());

            //判別方法②
            //DotSpatial.Topology.Polygon.IsWithinDistance(Point, double)
            sw.WriteLine("Method2 Polygon:{0} Point:{1} →{2}",
                fPoly.DataRow[0].ToString(),
                fPt.DataRow[0].ToString(),
                pg.IsWithinDistance(pt, 0).ToString());

            //判別方法③
            //DotSpatial.Data.Feature.IsWithinDistance(Feature, double)
            sw.WriteLine("Method3 Polygon:{0} Point:{1} →{2}",
                fPoly.DataRow[0].ToString(),
                fPt.DataRow[0].ToString(),
                fPoly.IsWithinDistance(fPt, 0).ToString());
        }
    }
}

これを実行した結果がResult.txtに書き出されます。

Method1 Polygon:A Point:1 →False
Method2 Polygon:A Point:1 →False
Method3 Polygon:A Point:1 →False
Method1 Polygon:A Point:2 →False
Method2 Polygon:A Point:2 →False
Method3 Polygon:A Point:2 →False
Method1 Polygon:A Point:3 →True
Method2 Polygon:A Point:3 →True
Method3 Polygon:A Point:3 →True
Method1 Polygon:A Point:4 →False
Method2 Polygon:A Point:4 →False
Method3 Polygon:A Point:4 →False
Method1 Polygon:A Point:5 →True
Method2 Polygon:A Point:5 →True
Method3 Polygon:A Point:5 →True
(後略)

と、3つ挙げたどの方法でも結果は変わらないようです。
時間があれば、3つの方法の処理時間の差とか、シェープファイルの測地系が違った場合にちゃんと結果が出てくるのかなどを試して見たいと思います。

つづく…のか!?



この記事の続きを書きました。