一つ前の記事の続きです。
シェープファイルに保存されたポイント(点)がポリゴン(面)に含まれるか否かをDotSpatialで判定する時に使った3つの方法での処理時間を比較してみます。
準備したシェープファイル(ポイントとポリゴン)は一つ前の記事と同じくこんな感じで、たとえばAのポリゴンの中には3・5のポイントが含まれています。
using DotSpatial.Data; using DotSpatial.Topology; using DotSpatial.Projections; /* 中略 */ //読み取るシェープファイル const string sPolygon = @"C:\hoge\Polygon.shp"; const string sPoint = @"C:\hoge\Point.shp"; //判定結果はテキストファイルへ const string sOut = @"C:\hoge\Result.txt"; //処理時間計測用 System.Diagnostics.Stopwatch swTime = new System.Diagnostics.Stopwatch(); //シェープファイルを開く・準備する using(PolygonShapefile psPoly = new PolygonShapefile(sPolygon)) using(PointShapefile psPt = new PointShapefile(sPoint)) using(StreamWriter sw = new StreamWriter(sOut, false, Encoding.UTF8)) { //Prjファイル読み取り psPoly.ReadProjection(); psPt.ReadProjection(); //読み取った結果を表示 Console.WriteLine("Poly :{0}", psPoly.Projection); Console.WriteLine("Point:{0}", psPt.Projection); //手法① //DotSpatial.Topology.Polygon.Contains(Point) swTime.Start(); foreach (Feature fPoly in psPoly.Features) { Polygon pg = new Polygon(fPoly.Coordinates); foreach (Feature fPt in psPt.Features) { Point pt = new Point(fPt.Coordinates[0]); if (pg.Contains(pt)) //重なり判定 { sw.WriteLine("Method1 Polygon:{0} Point:{1}", fPoly.DataRow[0].ToString(), fPt.DataRow[0].ToString()); } } } Console.WriteLine("Method1:{0}", swTime.ElapsedMilliseconds); //手法② //DotSpatial.Topology.Polygon.IsWithinDistance(Point, double) swTime.Reset(); swTime.Start(); foreach (Feature fPoly in psPoly.Features) { Polygon pg = new Polygon(fPoly.Coordinates); foreach (Feature fPt in psPt.Features) { Point pt = new Point(fPt.Coordinates[0]); if (pg.IsWithinDistance(pt, 0)) //重なり判定 { sw.WriteLine("Method2 Polygon:{0} Point:{1}", fPoly.DataRow[0].ToString(), fPt.DataRow[0].ToString()); } } } Console.WriteLine("Method2:{0}", swTime.ElapsedMilliseconds); //手法③ //DotSpatial.Data.Feature.IsWithinDistance(Feature, double) swTime.Reset(); swTime.Start(); foreach (Feature fPoly in psPoly.Features) { foreach (Feature fPt in psPt.Features) { if (fPoly.IsWithinDistance(fPt, 0)) //重なり判定 { sw.WriteLine("Method3 Polygon:{0} Point:{1}", fPoly.DataRow[0].ToString(), fPt.DataRow[0].ToString()); } } } Console.WriteLine("Method3:{0}", swTime.ElapsedMilliseconds); }
まずは、ポイントとシェープファイルの測地系を揃えた状態で実行してみます。
コンソールの標準出力1・2行目はコードの23・24行目で読み取ったProjetcitonの内容です。
そして、標準出力3~5行目がポリゴンに内包されるかの判定(コード:)にかかった時間。意外にも手法③のFeature.IsWithinDistance(Feature, double)の処理時間が短く、手法①のPolygon.Contains(Point)が一番時間がかかるという結果になりました。手法①と②はどちらもPolygonクラスを用いているものの、処理時間に10倍近く差があるのでContainsメソッドとIsWithinDistanceメソッドの処理速度の違いでしょう(むしろ後者の方が時間がかかりそうなのですが、不思議です)。
ちなみに出力結果は↓のとおりで、試した3つの手法で同じ結果が得られています。
Method1 Polygon:A Point:3 Method1 Polygon:A Point:5 Method1 Polygon:B Point:4 Method1 Polygon:C Point:6 Method2 Polygon:A Point:3 Method2 Polygon:A Point:5 Method2 Polygon:B Point:4 Method2 Polygon:C Point:6 Method3 Polygon:A Point:3 Method3 Polygon:A Point:5 Method3 Polygon:B Point:4 Method3 Polygon:C Point:6
関連記事