自動走行ロボットの走行プログラムを作成していると、事前に決めた領域にいるのかいないのか、ということを判定したくなることが結構あります。ここでは、その方法について調べた内容の備忘録を作成しました。
結論
shapelyという便利なライブラリが公開されているので、それを使用すると簡単に実現できます。
shapelyを用いて領域内外判定をする方法
shapelyを用いた領域判定は、多角形として領域を定義、判定という順番で行います。
例えば、以下のように4つの点で表される領域の内外判定をすることを考えてみます。
点は、左から順番に、(0.8, 4.3)、(1.2, 1)、(2.5, 5.7)、 (5.1, 3.4)とします。
まずは必要なクラスをインポートします。使用するのは、Pointと、Polygonです。
from shapely.geometry import Point, Polygon
Polygonクラスを用いて、先ほどの4つの点で表されるポリゴンは以下のようにして設定することができます。
# 4つの点を定義
p1 = (1.2, 1)
p2 = (0.8, 4.3)
p3 = (2.5, 5.7)
p4 = (5.1, 3.4)
# 多角形を定義
polygon = Polygon([p1, p2, p3, p4])
では、任意の点がこのポリゴンの内外にあるのかを判定してみましょう。
今回は具体例として、(3, 3)と(5, 2)に関して判定してみることにします。点は以下のように表します。
point33 = Point((3, 3))
point52 = Point((5, 2))
判定は以下のようにして実行します。
is_inside33 = polygon.contains(point33)
is_inside52 = polygon.contains(point52)
print(is_inside33) # 結果はTrue
print(is_inside52) # 結果はFalse
ランダムな大量な点について領域内外の判定をしてみる
xy軸それぞれについて、0~6の範囲でランダムにサンプリングして点を定義し、それが領域の内側か外側かを描画してみたところ以下のようになりました。内側の点は赤点、外側の点は黄色点で表しています。
これを試しに実行してみた方は以下のコードを実行してみてください。
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import Point, Polygon
# 4つの点を定義
p1 = (1.2, 1)
p2 = (0.8, 4.3)
p3 = (2.5, 5.7)
p4 = (5.1, 3.4)
# 多角形を定義
polygon = Polygon([p1, p2, p3, p4])
# ランダムな点を生成
num_points = 1000
random_points = np.random.rand(num_points, 2) * 6 # 0から6の範囲でランダムな点を生成
# 多角形内にある点を赤色、外にある点を緑色で分類
inside_points = []
outside_points = []
for point in random_points:
if polygon.contains(Point(point)):
inside_points.append(point)
else:
outside_points.append(point)
inside_points = np.array(inside_points)
outside_points = np.array(outside_points)
# 多角形を描画
polygon_x, polygon_y = polygon.exterior.xy
plt.plot(polygon_x, polygon_y, 'b-', label='Polygon')
# 多角形内の点を赤色、外の点を緑色で描画
if inside_points.size > 0:
plt.plot(inside_points[:, 0], inside_points[:, 1], 'ro', markersize=2, label='Inside Points')
if outside_points.size > 0:
plt.plot(outside_points[:, 0], outside_points[:, 1], 'yo', markersize=2, label='Outside Points')
# # 各頂点を描画
plt.plot(*zip(*[p1, p2, p3, p4]), 'bo', label='Vertices')
# 描画の設定
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Random Points in Polygon')
plt.legend()
plt.grid(True)
# グラフを表示
plt.show()