#author("2024-03-11T19:33:59+09:00","","")
#author("2024-03-11T19:57:52+09:00","","")
*多角形の内外判定 [#tb03a432]
以下のページを参考にしました。 ~
[[点の多角形に対する内外判定>https://www.nttpc.co.jp/technology/number_algorithm.html]]~

単純に実装すると、点が線分上にある場合、図形の向きで結果が逆になってしまいます。~
例を挙げます、次の図を見てください~

┏━━━━━━━━━━━━┓~
┃           /┃~
┃          / ┃~
┃         /  ┃~
┃   A    /   ┃~
┃       ・    ┃~
┃      /     ┃~
┃     /      ┃~
┃    /       ┃~
┃   /        ┃~
┃  /      B  ┃~
┃ /          ┃~
┃/           ┃~
┗━━━━━━━━━━━━┛~

↑AとBで結果が逆になる。~

参考にしたページではそういう仕様で進めているようですが、(図2-3)~
直感的には線分上は当たりとするか、~
完全に図形に入り込んでいるときのみ当たりにするかのどちらかの方がいいと思います。~

今回は、線分上に点がある場合は当たりとする処理にしています。~

**ソース [#i25eba58]
 #module
 //polygonは実数の配列でも整数の配列でも可
 //polygonは実数または整数の配列
 #defcfunc 多角形内外判定 array polygon, int 頂点数, double x, double y
	count = 0
	a_max = 頂点数 * 2
	
	for i,, a_max, 2
 
		始点 = polygon(i), polygon(i + 1)
		終点 = polygon((i + 2) \ a_max), polygon((i + 3) \ a_max)
 
		if 始点 != 終点{
			判定 = (x - 始点) * (終点.1 - 始点.1) / (終点 - 始点) + 始点.1 - y
		}else{
			判定 = (x != 始点) || ((y - 始点.1) * (y - 終点.1) > 0)
		}
		
		if 判定 < 0{
			if x < 始点 ^ x < 終点{
				if 始点 < 終点{
					count++
				}else{
					count--
				}
			}
		}else: if 判定 == 0{
			//点が線分上にある時
			return 1
		}
		
	next
	
	return count != 0
 #global

 #include "a2d.hsp"
 
 alcreateImage
 
 title "多角形内外判定"
 
 repeat
	stick key
 
	if key & 256{
		a(頂点数 * 2) = mousex, mousey
		頂点数++
	}
	if key & 512{
		頂点数 = limit(頂点数 - 1, 0)
	}
 
	判定結果 = 多角形内外判定(a, 頂点数, mousex, mousey)
	
	redraw 2
		alColor 240,240,240
		alFillRect 0,0,640,480
		alColor 0,0,0
		if 判定結果: alColor 200,100,50
		alFillPoly a, 頂点数
		alColor 50,130,30
		alDrawPoly a, 頂点数
		alCopyImagetoScreen
		pos 0, 0
		color
		mes "左クリック: 頂点を作成
		mes "右クリック: 最後に作成した頂点を削除
		mes ""+mousex+","+mousey + " : " + 判定結果
	redraw
 
	await 16
 loop