頂点の列が与えられたとき、それが凸多角形(convex)であるかどうかを判定する、という問題のようです。
「Aが凸多角形である」とは「Aに含まれる任意の2点p,qについて、pとqの全ての内分点がAに含まれる(ただし、Aの辺上にある点も、Aに含まれるものとします。)」ということで、つまり「Aに含まれる任意の2点p,qを結ぶ線分はAからはみ出さない」という意味です。この条件は「Aに含まれる任意の2頂点p,qについて、pとqの全ての内分点がAに含まれる」と言い換えることができ、さらに「Aに含まれる任意の隣り合う2頂点p,qについて、pとqの外挿点(「p,qを結ぶ直線からp,qを結ぶ線分を除いたもの」の上にある点)はAに含まれない」と言い換えても構いません。
あらすじとしては、点列a={(x[i],y[i])| i=1,2,...,n}の部分集合b={(x[i],y[i])| i=1,2,...,m}を頂点とする凸多角形の領域Bを作り、aの点が全てBに含まれるようにする。すると、a=bならば凹みはなく、a⊂b(a≠b)ならばaの要素のうちbに含まれない要素が、凹んでいる部分に相当します。
aからbを構成するアルゴリズムを構成すれば良いですね。たとえば
●aの隣り合う2点p=(x[i-1],y[i-1]),q=(x[i],y[i])を結ぶ直線に対して、aの全ての点がその直線の一方の側(たとえばqに立ってpを見たとき右側か左側)に含まれるなら、pかqはbの要素であり、さもなければpかqはbの要素ではない。このテストでbに含めない点を選び出せます。
具体的には、
p=(x[i-1],y[i-1]),q=(x[i],y[i])について、x,y座標からX,Y座標へ平行移動と回転による座標変換を行い、qを原点としpがX軸のX>0の部分に来るようにしてやります。
すなわち
X=(x[i-1]-x[i]) cosθ - (y[i-1]-y[i]) sinθ>0
Y=(x[i-1]-x[i]) sinθ + (y[i-1]-y[i]) cosθ=0
となるようなcosθ,sinθを求めます。
tanθ =- (y[i-1]-y[i])/(x[i-1]-x[i])
であるから、
θ=Arctan(- (y[i-1]-y[i])/(x[i-1]-x[i]) )
または
θ=π+Arctan(- (y[i-1]-y[i])/(x[i-1]-x[i]) )
であり、
(x[i-1]-x[i]) cosθ - (y[i-1]-y[i]) sinθ>0
を満たす方のθを選べば良い。
座標変換が決まったので、他の点(x,y)について、
Y=(x-x[i]) sinθ + (y-y[i]) cosθ
を計算します。aの全部の点について、全部Y≧0であるか、全部Y≦0であるならば、pとqを結ぶ直線(辺)は多角形Bの辺であることが分かります。Y>0となる点とY<0となる点が混在するようなら、pとqを結ぶ直線(辺)は多角形Bの辺ではない。このときは(つまり、多角形Aの辺のうち、Bの辺ではないものがあるのだから、Aは凸多角形Bとは異なり、ゆえに)Aは凹みがある。
別の方法として(こっちはspringsideさんやranxさんの回答とほとんど同じじゃないかな?)、
●aの点列が反時計回りに並んでいるものとします。aの隣り合う3点p=(x[i-1],y[i-1]),q=(x[i],y[i]),r=(x[i+1],y[i+1])について、x,y座標からX,Y座標へ平行移動と回転による座標変換を行い、qを原点としpがX軸のX>0の部分に来るようにしてやります。
さて、このときrの座標は
X=(x[i+1]-x[i]) cosθ - (y[i+1]-y[i]) sinθ
Y=(x[i+1]-x[i]) sinθ + (y[i+1]-y[i]) cosθ
に来ます。
で、点qを二つのグループのどちらに入れるかを決めます。
Y>0であるなら、点qを「グループ正」に分類します。
Y<0であるなら、点qを「グループ負」に分類します。
Y=X=0なら、q=r。qはどちらのグループにも入れません。
Y=0, X<0ならpとrを結ぶ線分上にqがある。qはどちらのグループにも入れません。
Y=0, X>0なら、pとqを結ぶ線分上にrがある。つまりqは突きだしているか引っ込んでいるわけで、全ての点が同じ線分上にあるのでない限り、aは凸多角形ではない。(こいつは例外扱いしましょう。)
以上の分類をaの全ての点についてやります。「グループ正」か「グループ負」、どちらか一方のグループが空集合になったら、aは凸多角形である。
お礼
ご回答ありがとうございます。 方針はだいたい分かるような気がするのですが、連立方程式を解かなくてはならないでしょうか。 ベクトルakに対し、Pk+2がその右側か左側かを判定するという操作をk=1,2,3...について行い、符合が混在すれば凹みが存在すると考えていいわけですね。 ベクトルakのX成分をxak、Y成分をyakで表すと、Pk+2の右側、左側は xak * yak+1 - xak+1 * yak で判定できそうな気がしますが、これでいいのでしょうか…。