線分の交差判定
Posted: 2012年9月17日(月) 18:59
Windows Vista Home Premium SP2 32ビット
Dev-C++5.2.0.3
gcc4.7.0
線分の交差判定のプログラムを作っています。
参考までに、方程式を使った古いプログラムを載せます。
さて、問題はこの古いコードではなく、この新しいコードです。
※引数の型が古い関数ではdoubleで、新しい関数ではintですが、仕様です
「ベクトルの外積の符号が違っていれば、交わっている」の部分では、
点3と点4が直線12(点1と点2を結ぶ直線)に関して反対側にあり、
かつ点1と点2が直線34に関して反対側にある場合に、「交わっている」と判定しています。
この考え方と実装で本当に正しく動作するでしょうか?
DXライブラリを用いて視覚化したプログラムを添付します。
動かしたい点の数字のキー(テンキーはだめ)を押しながらカーソルキーで点を動かせます。
このとき、シフトキーを押していると1ドットづつ動かせます。
よろしくお願いします。
Dev-C++5.2.0.3
gcc4.7.0
線分の交差判定のプログラムを作っています。
参考までに、方程式を使った古いプログラムを載せます。
► スポイラーを表示
int cross(int x1,int y1,int x2,int y2,
int x3,int y3,int x4,int y4) {
/* ベクトル */
long long b12x,b12y,b34x,b34y;
long long b24x,b24y;
long long b13x,b13y,b14x,b14y,b32x,b32y;
/* ベクトルの外積のz成分 */
long long g1213,g1214,g3431,g3432;
/* ベクトルの内積 */
long long n1213,n1214,n3431,n3432;
long long n2123,n2124,n4341,n4342;
/* 座標を引き算してベクトルを計算する */
b12x=x2-x1;b12y=y2-y1;
b34x=x4-x3;b34y=y4-y3;
b13x=x3-x1;b13y=y3-y1;
b14x=x4-x1;b14y=y4-y1;
b32x=x2-x3;b32y=y2-y3;
b24x=x4-x2;b24y=y4-y2;
/* 平面ベクトルをz成分が0の空間ベクトルとみなし、
外積のz成分を計算する */
g1213=b12x*b13y-b13x*b12y;
g1214=b12x*b14y-b14x*b12y;
g3431=b34x*(-b13y)-(-b13x)*b34y;
g3432=b34x*b32y-b32x*b34y;
/* ベクトルの内積を計算する */
n1213=b12x*b13x+b12y*b13y;
n1214=b12x*b14x+b12y*b14y;
n3431=b34x*(-b13x)+b34y*(-b13y);
n3432=b34x*b32x+b34y*b32y;
n2123=(-b12x)*(-b32x)+(-b12y)*(-b32y);
n2124=(-b12x)*b24x+(-b12y)*b24y;
n4341=(-b34x)*(-b14x)+(-b34y)*(-b14y);
n4342=(-b34x)*(-b24x)+(-b34y)*(b24y);
/* ベクトルの外積の符号が違っていれば、交わっている */
if(
((g1213<0 && g1214>0) || (g1213>0 && g1214<0)) &&
((g3431<0 && g3432>0) || (g3431>0 && g3432<0))
) return 1;
/* 線分の端が他方の線分上にあるので、交わっている */
if(
(g1213==0 && n1213>=0 && n2123>=0) ||
(g1214==0 && n1214>=0 && n2124>=0) ||
(g3431==0 && n3431>=0 && n4341>=0) ||
(g3432==0 && n3432>=0 && n4342>=0)
) return 1;
/* 交わっていない */
return 0;
}
「ベクトルの外積の符号が違っていれば、交わっている」の部分では、
点3と点4が直線12(点1と点2を結ぶ直線)に関して反対側にあり、
かつ点1と点2が直線34に関して反対側にある場合に、「交わっている」と判定しています。
この考え方と実装で本当に正しく動作するでしょうか?
DXライブラリを用いて視覚化したプログラムを添付します。
動かしたい点の数字のキー(テンキーはだめ)を押しながらカーソルキーで点を動かせます。
このとき、シフトキーを押していると1ドットづつ動かせます。
よろしくお願いします。