一つ前の記事の続きです。
シェープファイルに保存されたポイント(点)がポリゴン(面)に含まれるか否かを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
関連記事