プログラミングコンテストでは、「ある点が、与えらえた図形の中にあるかどうか?」を問うような問題が出されることが多々あります。そのような判定は内外判定と呼ばれますが、ここでは扇形に対する内外判定をpython3で実装する方法を紹介します。
「ある点が、扇形の中にあるか?」を判定するプロセス
扇形に対する内外判定は以下のプロセスで行います。
(1) その点は、扇形が属する円の中にあるか?
(2) 扇型の中心角は180°未満か?
・中心角が180°未満であれば、
(3) その点は開始角より左側にあるか?
(4) その点は終了角より右側にあるか?
・中心角が180°以上であれば、
(3′) その点は開始角より右側にあるか?
(4′) その点は終了角より左側にあるか?
また上に出てきた、中心角・開始角・終了角 とは以下の図に示すとおりです。緑色の部分を扇形としています。
python3での実装
先に、ある点に対する扇形の内外判定を行うコード全体を以下に示します。
このコードは Check_FanShape( ) という関数として記述しており、ある点が扇形の中にあれば True、なければ Falase を返します。
import math
def Check_FanShape(target_x, target_y, center_x, center_y, start_angle, end_angle, radius):
# (0) 距離及び座標の準備
distance_x = target_x- center_x
distance_y = target_y- center_y
start_x = math.cos(math.radians(start_angle))
start_y = math.sin(math.radians(start_angle))
end_x = math.cos(math.radians(end_angle))
end_y = math.sin(math.radians(end_angle))
# (1) その点は、扇形が属する円の中にあるか?
if distance_x ** 2 + distance_y ** 2 > radius** 2:
return False
# (2) 扇型の中心角は180°未満か?
# 180°未満である場合
if end_angle - start_angle < 180:
# (3) その点が開始角より右側にあれば範囲外
if start_x * distance_y - distance_x * start_y < 0:
return False
# (4) その点が終了角より左側にあれば範囲外
if end_x * distance_y - distance_x * end_y > 0:
return False
# 扇型の内部にある!
return True
# 180°以上である場合
else:
# (3') その点が開始角より左側にあれば範囲外
if start_x * distance_y - distance_x * start_y >= 0:
return True
# (4') その点は終了角より右側にあれば範囲外
if end_x * distance_y - distance_x * end_y <= 0:
return True
# 扇型の外部にある
return False
以下に、コードの詳細をみていきます。
Check_FanShape( ) に対する引数
この関数では7つの引数を使用しています。
- target_x:調べたい、ある点の x 座標の値
- target_y:調べたい、ある点の y 座標の値
- center_x:扇形の中心点の x 座標の値
- center_y:扇形の中心点の y 座標の値
- start_angle:扇形の開始角 ※ここでの角度は度数法です。
- end_angle:扇形の終了角 ※ここでの角度は度数法です。
- radius:扇形の半径
(0) 距離及び座標の準備
ここでは、以降で使用するそれぞれの値を取得しています。
x座標とy座標の取得では、三角関数を使用していますがその詳細についてはこちらのサイトが大変参考になります。
(1) その点は、扇形が属する円の中にあるか?
三平方の定理を利用し、円の半径と比較することで内外判定を行っています。
(2) 扇型の中心角は180°未満か?
ここからは、ベクトルの外積を利用して判定を行っていきます。
その判定の理屈についてはやや難しいので説明を省きますが(実は良くわかっていない。。)、四角形(平行四辺形)の面積を比較して判定するといったイメージでしょうか。ベクトルの外積と平行四辺形の関係については、こちらのサイトがとても勉強になります。
また、その判定の際、扇形の中心角が180°未満か、180°以上か、で符号を反転させる必要があるため、ここの if 分で条件分岐させています。
(3)~(4)(および(3′)~(4′))開始角と終了角の間にあるか?
扇形の中心角が180°未満の場合、
対象とする点が開始角より右側にあれば False を返し、
終了角より左側にある場合も Falseを返します。
上記の2つを抜ければ、扇形の中にあるということになり、Trueを返します。
同様に、
扇形の中心角が180°以上の場合、
対象とする点が開始角より左側にあれば False を返し、
終了角より右側にある場合も Falseを返します。
上記の2つを抜ければ、扇形の中にあるということになり、Trueを返します。
以上が、python3 での扇形に対する内外判定になります。