• ベストアンサー

閉曲線の凹みの判定法

座標の列(x1,y1),(x2,y2),...,(xn,yn)で与えられる、各点が次の点と接続する閉曲線があります((xn,yn)は(x1,y1)に接続します)。 この曲線のどこかに凹みがあるかどうかを判定するにはどうしたらよいのでしょうか?

  • mide
  • お礼率95% (422/443)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

ちょっと面倒ですが、「ベクトルの回転」を考え、その「回転角」から判定できるのではないでしょうか。 今、点(xk,yk)を点Pkとします。 PkからPk+1へ行く矢印をベクトルakとします。 (ただし、ベクトルanは、PnからP1へ行くベクトル) ベクトルa1,a2,a3,・・・は長さが違うので、同じ長さにするために、各ベクトルのx成分とy成分を、そのベクトルの大きさ√(xk^2+yk^2)で割って、長さを1に揃えます。 そのようにして長さが1に揃ったベクトルをbkとします。 bk+1は「bkを角度θ回転させたもの」とすれば、原点中心のθk回転(1次変換)を表す行列Akを用いて、 bk+1 = Ak・bk・・・※ と書けます。 ただし、   cosθk  -sinθk A =   sinθk  cosθk です(行列を表す括弧は省略しました)。 さて、※を成分に分解すると、sinθk、cosθkを変数とする連立方程式になりますので、これを解いてsinθkを求めます。 以上により、sinθ1、sinθ2、sinθ3、・・・というふうにn個のsinが求まりますが、  ・その符号が全部同じであれば、凹みなし  ・符号の中にプラスとマイナスが混在すれば凹みあり ということになると考えられます。 以上は、常に同じ方向に回転しているか、逆回転が混在しているか、ということから判定しています。 計算は面倒ですが、コンピュータでやればすぐにできると思います。

mide
質問者

お礼

ご回答ありがとうございます。 方針はだいたい分かるような気がするのですが、連立方程式を解かなくてはならないでしょうか。 ベクトルakに対し、Pk+2がその右側か左側かを判定するという操作をk=1,2,3...について行い、符合が混在すれば凹みが存在すると考えていいわけですね。 ベクトルakのX成分をxak、Y成分をyakで表すと、Pk+2の右側、左側は xak * yak+1 - xak+1 * yak で判定できそうな気がしますが、これでいいのでしょうか…。

その他の回答 (4)

  • stomachman
  • ベストアンサー率57% (1014/1775)
回答No.5

三角関数を使いたくない、なるべく速く計算したい、頂点の数は多い、という条件を入れるんですね。 No.4の第一の方法は、実際に回転を計算しないでも、一次不等式として扱えばできそうです。ただ、この方法は頂点の個数の二乗に比例する手間が掛かるのが難点です。 No.4の第二の方法も実際に回転を計算しないで、二つのベクトル(p→qとq→r)の外積の符号を見れば良いでしょう。(三点が直線上に並ぶという場合の扱いをきちんと検討する必要がありそうですが。)この方法の手間はnに比例するから速い。 ただ、ひとつ問題があって、多角形Aの辺が自分自身と交差している場合(NTTのロゴマークのような形のとき)に、Aを凸多角形だと判定してしまう可能性があります。 ●さらに別の方法として、 隣り合っていない頂点の中点をひとつ選んでmとします。mと各頂点を結ぶ補助線を引いて、多角形Aを三角形に分割して、それぞれの面積を計算するんです。(面積は外積で計算します。) 隣り合う頂点p,q,rについて、 |(三角形pmqの面積)|+|(三角形qmrの面積)|<|(三角形pmrの面積)| であれば、頂点qは凹んでいる、と分かります。 同時に、面積の符号をチェックします。面積の符号が三角形によって異なる場合があれば、それは多角形Aの辺が自分自身と交差しているか、あるいはmがAの外にあることを意味します。 多角形Aの辺が自分自身と交差していれば、これは凸多角形ではない。 2頂点の中点であるmがAの外にあるなら、やはりこれは凸多角形ではない。 手間はnに比例です。 外積については、たとえばhttp://yosshy.sansu.org/gaiseki.htm

mide
質問者

お礼

ほぼ解決したと思います。ありがとうございました。

  • stomachman
  • ベストアンサー率57% (1014/1775)
回答No.4

頂点の列が与えられたとき、それが凸多角形(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は凸多角形である。

mide
質問者

お礼

詳しいご回答ありがとうございます。 >頂点の列が与えられたとき、それが凸多角形(convex)であるかどうかを判定する、という問題のようです。 その通りです。実データが閉曲線のサンプリング値なもので、つい分かりにくいタイトルにしてしまいました。 >●aの隣り合う2点p=(x[i-1],y[i-1]),q=(x[i],y[i])を結ぶ直線に対して、aの全ての点がその直線の一方の側(たとえばqに立ってpを見たとき右側か左側)に含まれるなら、pかqはbの要素であり、さもなければpかqはbの要素ではない。 これはよく分かりますし、比較的簡単に計算できそうです。 第2の方法なんですが、私が#2のお礼に書いた判定法ではだめでしょうか。点がたくさんあるため、三角関数計算が避けられればそれに越したことはないので。 どの部分が凹といった情報は不要で、全体として凹部の有無が判定できればいいのですが。

回答No.3

#2のspringsideです。 私が書いたやり方だと、「凹」の場合だけでなく、「凸(出っ張り)」の場合も判定されてしまうことに気が付きました。 閉曲線(と言うか、正確には多角形)の各辺をベクトルと見たときに、その方向(全体として右回りか左回りか)も含めて考慮しなければならないようです。 という訳で、私の解答ではマズイです。 なお、 >>ベクトルakに対し、Pk+2がその右側か左側かを判定するという操作をk=1,2,3...について行い、符合が混在すれば凹みが存在すると考えていいわけですね。 →そういう考え方です。 >>連立方程式を解かなくてはならないでしょうか。 →連立方程式の組の数は多いでしょうが、それぞれがたった2変数(2元連立方程式)なので、手間はかからないと思いますが。

mide
質問者

お礼

再度ご回答ありがとうございます。 >私が書いたやり方だと、「凹」の場合だけでなく、「凸(出っ張り)」の場合も判定されてしまうことに気が付きました。 すみません、これがよく分かりません…。凸(出っ張り)しかないのに、符号が混在することがあるでしょうか(この問題では「凸」という字の形にも凹部があります)。 シンプルで良い方法に思えたのですが。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.1

参考URLは以前私がした質問で、もちろん今回の質問とは異なります。 ただ、No.10の回答に対するお礼を見て頂きたいのですが、 「回転の中心」を判断の基準にしようという回答に対し、 私は「閉曲線の内側」で判断した方が良いと考えました。 この違いの生ずるところが、まさに凹みの部分です。 ちなみに曲線が右回りか左回りかということは、面積が 正か負かということに置き換えることができます。 考えてみて下さい。

参考URL:
http://oshiete1.goo.ne.jp/kotaeru.php3?q=289549
mide
質問者

お礼

参考質問をどう応用したらよいかよく分からなかったのですが、#2のspringsideさんの回答と合わせて考えてみます。 ありがとうございました。

関連するQ&A

  • 閉曲線の向きの判定法

    閉曲線の向きの判定法 平面上に交差していない1本の閉曲線があります。 この閉曲線上の座標点配列がちょうど1周分与えられている  (x0,y0),(x1,y1),(x2,y2), ... (xn,yn) とき、この座標配列の向きが時計回りになっているか 反時計回りになっているかを判定する方法を教えてください。

  • 多角形の内部かどうか判定する方法

    2次元座標系にあるn個の点を順に接続して多角形を作ります。 n個の点は(x1,y1)-(x2,y2)-…-(xn,yn)とします。 (xn,yn)と(x1,y1)を最後につないで閉じた多角形とします。 このとき点(a,b)が多角形の内部にあるかどうかを判定するにはどのようにしたら良いでしょうか? 辺同士が交わるような点の配置は無いとします。 よろしくお願いします。

  • 行列式に関する質問です。

    行列式に関する質問です。 ファンデルモンドの行列式を用いて、「座標平面のn個の点(x1,y1)…(xn,yn)を通る(n-1)次曲線 y=a(n-1)x^(n-1)+a(n-2)x^(n-2)+…+a1x+a0はただ一つであることを示せ。」という問題です。 どの様にして証明すればいいのでしょうか?よろしくお願いします。

  • 点がx軸上に来ない

    ある問題で、「点Pn(Xn,Yn)がx軸上に来ないことを示せ」とあり、点Pnのy座標(=Yn)が5の倍数でないことまで判明しています。 しかし、その後行き詰まり、解答を見たところ… 「Ynは5の倍数でない。すなわち、点Pのy座標は0となることはないから、点Pはx軸上に来ない(終)」 となっていました。この「すなわち」の言いかえがどうも分かりません。 どなたか教えてください。

  • mathematicaでリストの格納

    mathematicaでTable関数で作成したリスト {{x1, y1, z1, f(x1,y1,z1)}, {x2, y2, z2, f(x2,y2,z2)}, ... , {xn, yn, zn, f(xn,yn,zn)}} 中のx1~xnまでの各成分とy1~ynまで(、z1~znまで、 f(x1,y1,z1)~f(xn, yn, zn)までの各成分)をそれぞれ配列に格納するにはどうすればいいのでしょうか?(C言語のようにループ文で配列に格納することはできないのでしょうか?) もしくは、行列中で列の成分を取り出すことはできますか? どなたか解法を示していただければ幸いです。

  • n角形の頂点を通るy軸に平行な直線とn角形の公差部

    xy平面上に P1(x1, y1), P2(x2, y2), ..... Pn(xn, yn) の n角形がある時、各点を通る y軸に平行な直線と n角形の交差部の長さを計算する方法を考えています。 図で示された赤線の長さを計算したいのです。 座標値が定数なら方程式で解けますが、座標値が変数の場合にどのようなアルゴリズムでプログラムすれば良いいのか、途方に暮れています。 どなたか、お知恵を拝借願います。

  • 論理回路

    2n変数論理関数 fn(x1,x2,...,xn,y1,y2,...,yn)={ 1 N(x1,x2,...,xn)>N(y1,y2,...,yn)の時                 0 その以外 について、以下の問に答えよ。ここで、Nは入力を2進数とみなしたときの数を値として持つ関数であり、N(x1,x2,...,xn)=Σ(i=1~n)xi2^n-iと表すことができる。 問 任意のn>=2に対して     fn(x1,x2,...,xn,y1,y2,...,yn)= x1・y1(bar) + (x1+y1(bar))・fn-1(x2,...,xn,y2,...yn) が成り立つことを示せ。ただし、(bar)が論理否定、・が論理積、+は論理和を表す という問なのですが、どのように証明をすればよいのでしょうか? お願いします。

  • 代数学☆イデアルの問題!!

    次の問題について教えてください!! N:自然数 R:環 L,M:左イデアル LM={x1・y1+x2・y2+・・・+xn・yn |         xi∈L,yi∈M (i=1,2,・・・,n),n∈N} LMがイデアルであることを示せ。 左イデアルであることは示せたんですが、右イデアルであることが示せません。 右イデアルを示すために a∈LM,r∈Rに対して a=x1・y1+x2・y2+・・・+xn・yn (xi∈L,yi∈M) とおくと、 a・r=(x1・y1+x2・y2+・・・+xn・yn)・r    =(x1・y1)・r+(x2・y2)・r+・・・+(xn・yn)・r    =x1・(y1・r)+x2・(y2・r)+・・・+xn・(yn・r) になって、 a・r∈LMを示すのにyi・r∈Mを示すのかな、と思ったのですが、 どう示すのか分りません。  やり方自体間違っているのでしょうか、それともyi・r∈Mを示す方法があるのでしょうか。教えてください!!

  • perlを使ってファイル分割

    ーーーーーーーーーーーー SRR_1 X1 Y1 SRR_1 X2 Y2 ~ SRR_1 Xn Yn SRR_2 X1 Y1 SRR_2 X2 Y2 ~ SRR_3 X1 Y1 ~ SRR_xxx X1 Y1 ーーーーーーーーーーー このようなタブ区切りのファイルを、一列目のSRR以降の数字が変わるごとに以下のようにファイルを分割したいと思っています。 SRR_1.txt ーーーーーーー X1 Y1 X2 Y2 ~ Xn Yn ーーーーーーー SRR_2.txt ーーーーーーー X1 Y1 ~ Xn Yn ーーーーーーー perl初心者ですが、どうかよろしくお願いします。

    • ベストアンサー
    • Perl
  • 最小二乗法 お願いします。テスト前で急いでいます

    N個の点列(x1,y1),(x2,y2),,,,,,,(xn,yn)に対する、三次の最小二乗法を求める式を教えてください