電子書籍の厳選無料作品が豊富!

配列 x, y に(実数)値が与えられており、
(x[1], y[1]) を座標平面上の点 P1 、(x[2], y[2]) を点 P2 、…
と考えたとき、

P1とP2を結んだ線分と、P3とP4を結んだ線分が交差しているかを判断する
プログラム(アルゴリズム)はどのように考えることができるでしょうか?
結ぶ2点を通る直線の傾きなどを求めても、どのように利用すればよいか思いつきませんでした。

C言語というより数学の話かもしれませんが、ご教示いただければ幸いです。
なかなか方法を思いつかず、私の考察を提示できずに恐縮ですが宜しくお願いいたします。

A 回答 (6件)

完全にまたがる場合のみ交差とする、ってことでしたね。


勘違いしていました。失礼しました。

> なぜ外積値から判定できるのかについて理解しきれていませんが…。
一応、補足しておきますが、説明が下手ですみません。
(P1→P2)×(P1→P3) のベクトル方向を考えた場合、
(P1→P2)から(P1→P3)に(180度未満で重なる方向に)回転させて右ねじの進む方向が外積のベクトル方向となります。
このことから、
(P1→P2)×(P1→P3)のz成分 > 0 なら P3 は(P1→P2)の左側、
(P1→P2)×(P1→P3)のz成分 < 0 なら P3 は(P1→P2)の右側
ということになります。

したがって、
2点(P3とP4)がベクトル(P1→P2)の左右に分かれる場合、外積のz成分が正負に分かれる(z成分同士の積は負)ということになります。
線分P3P4が直線P1P2をまたがるということです。

2点が共にベクトルの左側(あるいは右側)であれば、z成分は共に正数(あるいは負数)となり、z成分同士の積は正ということになります。
線分P3P4は直線P1P2をまたがらないということです。
    • good
    • 0
この回答へのお礼

改めて回答いただきありがとうございます。
失礼だなんて恐縮です。
本当にありがとうございます。

自分でも、なんとなく~が…のとき右側で、、
などと曖昧にしか認識できていなかったのですが、
頂いた回答を参照しつつ、(z成分が0でも)三次元ベクトルの外積の進む方向について考えたら、うまく理解(説明)することができました。

座標平面上の操作であったために、z成分(成分というより感覚的な三次元)の概念を捨ててしまっていました。
三次元で考えると、時計回り、反時計回り、右ねじ、といった語を用いてうまく説明がつきました。

ありがとうございました。
恐らくこれ以上の回答はつかないので適当に締め切らさせていただきます。

お礼日時:2007/01/04 17:25

ベクトルの外積を利用して実装されるということなので、少し補足しておきます。


実際に使用されるのは外積の z 成分のみですので、2つの外積の z 成分の積が0以下という条件でよいことになります。

気をつけて欲しいのは、2つの線分が同一直線上にある場合(外積の大きさが2つとも0の場合)についての考慮がしてありませんので、その辺の判定も盛り込むようにしてください。
    • good
    • 0
この回答へのお礼

補足していただきありがとうございます。

今回、結ばれる点が、他の点の線分をまたいでいない場合は交差していないものとして考えています。
#3のお礼でも示しましたが、面積値を算出するプログラムの一部で利用しています。

辺(線分)が交差する場合のみ、その値に影響がでてしまうため判定を試みています。
そのため、その場合のみを判定して、

( (P1→P2)×(P1→P3) * (P1→P2)×(P1→P4) ) < 0
かつ
( (P3→P4)×(P3→P1) * (P3→P4)×(P3→P2) ) < 0
のときに交差していると評価しています。

外積が0であれば、外積値の積は負にはなりませんので交差していないという評価でも問題ないはずです。

何か誤解していたら恐縮ですが…。
ありがとうございます。

お礼日時:2007/01/03 15:14

線分同士の交差判定には定石があります。



P1とP2を結ぶ直線は
(y-y[1])(x[2]-x[1]) - (y[2]-y[1])(x-x[1]) = 0 … (1)

P3とP4を結ぶ直線は
(y-y[3])(x[4]-x[3]) - (y[4]-y[3])(x-x[3]) = 0 … (2)

・(1)の左辺のx,yにP3の座標を代入したもの

・(1)の左辺のx,yにP4の座標を代入したもの
の積が0以下

かつ

・(2)の左辺のx,yにP1の座標を代入したもの

・(2)の左辺のx,yにP2の座標を代入したもの
の積が0以下

であれば、線分同士は交差しています。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

#1の回答を頂いて、仰られるような流れを考えたのですが途中で分からなくなってしまいました。
考えていたことの解を頂き大変参考になりました。

お陰様で、座標の具体値を与えて判定操作を追跡することができました。
ありがとうございました。


# 皆様から回答いただき、本件に関して疑問を解消することができました。
ありがとうございます。
これ以上回答が付かないようであれば適当に締め切らさせていただきます。
失礼致します。

お礼日時:2007/01/03 04:06

まったく視点を変えてベクトルで考えてみてはどうでしょう。


(質問者様へ、ベクトルわからなかったら聞き流しておいてください。)

ベクトルP1P3とP1P2の外積とP1P4とP1P2の外積(以後、P1P4×P1P2 と書きます)の方向が反対なら、線分P3P4は直線P1P2と交差することになります。
P1P3×P1P2 の大きさが0の場合はP1、P2、P3は同一直線上にあることになります。

したがって、2つの線分が交差する条件は次のような式になります。
if (((P1P3×P1P2 と P1P4×P1P2 の方向が反対) || (P1P3×P1P2 か P1P4×P1P2 のどちらかのみ大きさが0)) &&
  ((P3P1×P3P4 と P3P1×P3P4 の方向が反対) || (P1P3×P1P2 か P1P4×P1P2 のどちらかのみ大きさが0))){
   2つの線分は交差
}

ベクトルなんて遥か昔の記憶なのですが、たぶん考え方は合っていると思います。(数学得意な方、間違い指摘していただけるとありがたいです^^;)
    • good
    • 0
この回答へのお礼

方法のご教示ありがとうございます。

なるほど。この方法で判定できるのですね。
この考え方を用いて実装させていただきました。
なぜ外積値から判定できるのかについて理解しきれていませんが…。

http://oshiete1.goo.ne.jp/qa2629260.html
この別の質問と関連しているのですが、もう少し数学に関する理解力を付けないとですね;

お礼日時:2007/01/03 03:59

>2直線の式はなんとか出せるのですが、


>プログラム上でこの式をどのように扱えばよいか悩んでしまいました。

直線の式を出すだけではなく、それらを用いて交点の座標を表す式まで計算しないとコードには持っていけませんよね。

>直線がy軸に平行であったり、交わらない場合の交点を算出しようとするあたりの対応で止まってしまいました…。

このあたりの場合分けが必要な計算(分母が0になる可能性がある等)は方程式を手計算で解く段階で洗い出せるかと思います。
今回の場合は仰るとおり「いずれか、もしくは両方の直線がy軸に平行な場合」と「2直線の傾きが等しい場合」が出てくるようです。
普通に方程式を解くときと同様にこれらを場合分けしてコーディングすれば良いのではないでしょうか。

また、交わらない場合に交点を算出する事に関しては、#1さんの仰るとおり、とりあえず線分ではなく直線と思って交点を出して、それがもとの線分の上にあるかを調べれば良いでしょう。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
> 直線の式を出すだけではなく、それらを用いて交点の座標を表す式まで計算しないとコードには持っていけませんよね。
交点座標を求めようとしたあたりでこんがらがってしまいました。

プログラミング以前の数学の時点で悩んでしまうだなんてお恥ずかしい限りです。

お礼日時:2007/01/03 03:48

線分の交点を求め、その交点が両方の線分上にあれば交差していると考えられます。


交点が、線分の端点と同じ場合は、交差していないという判断でいいのかな?

後は、実際にプログラムを作ってみて、うまくいかなかったら、再度質問してみてください。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
点が線分と重なる場合や、線分同士が重なる場合は交差していないものとして構いません。
結ばれる点が、他の結ばれる点の線分をまたいでいる場合を評価したいと思っております。

結ばれる2点を通る直線の傾きを求め、2直線の式はなんとか出せるのですが、
プログラム上でこの式をどのように扱えばよいか悩んでしまいました。
直線がy軸に平行であったり、交わらない場合の交点を算出しようとするあたりの対応で止まってしまいました…。

与えられた座標に対して自分で数学的に判断することは容易ですが、
一般的にプログラムするとなるとややこしくなってしまいますね。

お礼日時:2007/01/02 19:18

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!