ユーザーが地図上に複雑なポリゴンを描画し、特定の経度/緯度がそのポリゴン内にあるかどうかをアプリケーションにチェックさせる必要があります。
地球の曲率を補正しない単純なx/yデカルト座標系を使用しているアルゴリズムしか見つけることができませんでした。
ユーザーはPCでポリゴンを描画し、そこでポイントが無線を介して組み込みデバイスに転送されます。組み込みデバイスは、指定されたポリゴンが現在の位置(GPSから取得)内にあるかどうかを確認する必要があります。
これは組み込みデバイス用であるため、巨大なライブラリを使用することはできません。むしろ、自分でチェックを実行するためのアルゴリズムまたは非常に小さなライブラリが必要です。しかし、私はそのようなアルゴリズムを見つけることができないようです。
これは、頂点のリストを含むPolygonクラス用にC#で作成した実装です。地球の曲率は考慮されていません。むしろ、これを実行する前に、ポリゴンをより小さなセグメントに前処理します。
このアルゴリズムのパフォーマンスは非常に優れています。何千ものエッジを持つポリゴンの場合でも、デスクトップでは約1〜2ミリ秒で完了します。
コードはかなり最適化されているため、擬似コードほど読みやすくありません。
public bool Contains(GeoLocation location)
{
if (!Bounds.Contains(location))
return false;
var lastPoint = _vertices[_vertices.Length - 1];
var isInside = false;
var x = location.Longitude;
foreach (var point in _vertices)
{
var x1 = lastPoint.Longitude;
var x2 = point.Longitude;
var dx = x2 - x1;
if (Math.Abs(dx) > 180.0)
{
// we have, most likely, just jumped the dateline (could do further validation to this effect if needed). normalise the numbers.
if (x > 0)
{
while (x1 < 0)
x1 += 360;
while (x2 < 0)
x2 += 360;
}
else
{
while (x1 > 0)
x1 -= 360;
while (x2 > 0)
x2 -= 360;
}
dx = x2 - x1;
}
if ((x1 <= x && x2 > x) || (x1 >= x && x2 < x))
{
var grad = (point.Latitude - lastPoint.Latitude) / dx;
var intersectAtLat = lastPoint.Latitude + ((x - x1) * grad);
if (intersectAtLat > location.Latitude)
isInside = !isInside;
}
lastPoint = point;
}
return isInside;
}
基本的な考え方は、テスト対象のポイントの「x」位置にまたがるポリゴンのすべてのエッジを見つけることです。次に、それらのうちのいくつが、ポイントの上に伸びる垂直線と交差するかを見つけます。偶数がポイントの上を横切る場合、あなたはポリゴンの外側にいます。奇数が上を横切る場合、あなたは中にいます。
あなたのニーズに変換できる良い説明と簡単なCコード
http://alienryderflex.com/polygon/
重なり合わないポリゴンが多数ある場合は、ポリゴンチェックをRTreeと組み合わせて、検索ツリーをすばやくカリングします。