関数
XZ平面における交差判定の関数。引数は線分1の始点、終点、線分2の始点、終点、交差座標となる。
//
// 線分の交差判定
//
int IsIntersectLinesXZ(vector A; vector B; vector C; vector D; export vector Cross)
{
// 直線にタッチしているポイントも考慮するための許容誤差
float epsilon = 0.0001;
int result = -1;
float denominator = (B.z - A.z) * (D.x - C.x) - (B.x - A.x) * (D.z - C.z);
if(denominator != 0)
{
float s = ((B.x - A.x) * (C.z - A.z) - (B.z - A.z) * (C.x - A.x)) / denominator;
if(s >= 0 - epsilon && s <= 1.0 + epsilon)
{
float r = ((A.x - C.x) * (D.z - C.z) - (A.z - C.z) * (D.x - C.x)) / denominator;
if(r >= 0 - epsilon && r <= 1.0 + epsilon)
{
result = 1;
Cross = A + (B - A) * r;
}
}
}
return result;
}
変数epsilonに閾値を入れる。小さい値にするほど判定が厳しくなり、大きい値にするほど許容範囲が広くなる。
使用例
交差座標を格納するベクトル型変数crossを事前に用意している。関数を実行するとcrossに座標が入る。
vector A = set(-3,0,1);
vector B = set(3,0,-3);
vector C = set(5,0,0);
vector D = set(-4,0,-4);
vector cross;
int isIntersect = IsIntersectLines(A, B, C, D, cross);
printf(sprintf('%g', isIntersect) + '\n');
// 1
printf(sprintf('%g', cross) + '\n');
// {1.1,0,-1.73333}
解説
線分ABと線分CDを考える。
点Pは線分AB上のポイント、点Qは線分CD上のポイント。
P = A + (B – A) * r
Q = C + (D – C) * s
P=QなのでA + (B – A) * r = C + (D – C) * s
A.x + (B.x – A.x) * r = C.x + (D.x – C.x) * s
A.y + (B.y – A.y) * r = C.y + (D.y – C.y) * s
が成り立つので、
r = ( (C.x – A.x) + (D.x – C.x) * s ) / (B.x – A.x)・・・①
s = ( (A.y – C.y) + (B.y – A.y) * r ) / (D.y – C.y)・・・②
①を変形させる
s = ( (A.x – C.x) + (B.x – A.x) * r ) / (D.x – C.x)
②との等式にすると
( (A.y – C.y) + (B.y – A.y) * r ) / (D.y – C.y) = ( (A.x – C.x) + (B.x – A.x) * r ) / (D.x – C.x)
rでまとめると
r = ( (A.x – C.x) * (D.y – C.y) – (A.y – C.y) * (D.x – C.x) ) / ( (B.y – A.y) * (D.x – C.x) – (B.x – A.x) * (D.y – C.y) )
となる。今度は②を変形させる
r = ( (C.y – A.y) + (D.y – C.y) * s ) / (B.y – A.y)
①との等式にしてまとめると
s = ( (B.x – A.x) * (C.y – A.y) – (B.y – A.y) * (C.x – A.x) ) / ( (B.y – A.y) * (D.x – C.x) – (B.x – A.x) * (D.y – C.y) )
となる。
分母d = ( (B.y – A.y) * (D.x – C.x) – (B.x – A.x) * (D.y – C.y) )
とすると
s = ( (B.x – A.x) * (C.y – A.y) – (B.y – A.y) * (C.x – A.x) ) / d
r = ( (A.x – C.x) * (D.y – C.y) – (A.y – C.y) * (D.x – C.x) ) / d
となる。dが0の時に線分は平行となり、sとrがともに0~1の範囲のときに交差しているとみなせる。