구(Sphere)와 편선(偏線, Ray)의 교차

시작점에서 어떤 방향으로 무한히 뻗어 나가는 선을 편선(Ray)이라고하자.  시작점 p와 방향벡터 d로 정의된 편선이 있을때, 이 편선이 구(Sphere)와 교차하는지 확인하는 방법에 대해 생각해보자. 교차한다면 교차점은 하나 인가, 아니면 두개인가? 아래의 그림은 여개의 상황을 보여준다.

사용자 삽입 이미지
첫번째 질문은 편선과 구가 교차하는지의 여부인데, 이를 위해서 구의 중심점에서 편선까지의 거리를 구해야만 한다. 만약 그 거리가 구의 반지름보다 크다면 교차하지 않는다고 할 수 있다.

거리를 구하기 위해, 2가지 경우를 고려해야 하는데… 구의 중심점이 편선에 투영되는지 투영되지 않는지이다. 이는 내적을 통해 알 수 있다.

구의 중심점을 c라고 하고, p에서 c까지 가는 벡터를 v라고 하자.  그렇다면 만약…….

  • d ∙ v > 0 이면 투영되므로 거리를 구할 수 있다는 것이고
  • d ∙ v <= 0 이면 편선 뒤에 구가 있어 투영되지 않아 거리를 구할 수 없다는 것이다.

사용자 삽입 이미지
위의 두 경에 대해서 편선과 구와의 교차에 대해 살펴보도록 하자.

구의 중심점이 편선에 투영될 경우

아래의 그림은 투영될 경우에 대해서 가능한 3가지 경우이다. 구A는 교차하지 않는 것이고, 구B는 한 점에서만 교차하고 구C는 2점에서 교차한다.

사용자 삽입 이미지
편선 위에 구의 중심점의 투영을 계산해보자. pc를 투영된 점이라고 하면, 구A에 대한 편선 위의 투영점은 pcA이고 구B에 대한 것은 pcB, 구C에 대한 것은 pcC가 된다. pc에서 구의 중심점까지의 거리가 구의 반지름보다 크다면 교차하지 않는 것이고 구A가 그렇다. pc에서 구의 중심점까지의 거리가 구의 반지름과 같다면 한점에서 만나는 것이고 구B가 그 경우이고 교차점은 점 pc이다.

구C에 대한 경우는 반지름보다 그 거리가 작은 경우이고 2개의 교차점이 존재하며 이 2개의 교차점을 구하기 위해서는 좀더 생각을 해야 하는데… 다음과 같다.

사용자 삽입 이미지
먼저 점 pc는 내적을 이용한 투영을 통해 구할 수 있다. 투영법은 이 블로그의 투영에 관한 글을 참조하기 바란다. 그리고 두개의 교차점을 i1, i2라고 하자. 다음의 과정을 통해 i1을 얻을 수 있다.

p에서 i1까지 거리를 알고 있다고 가정하면, 이 거리를 di1이라고 하고 i1은 다음 공식을 통해 구할 수 있다.

i1 = p + d * di1

위의 공식에서 p와 d는 이미 알고 있으므로, di1을 구하는 것만 남게 된다. 점i1, pc, c로 구성된 삼각형이 직각삼각형이므로, 피타고라스(Pythagorean) 공식을 적용해보면, 삼각형의 변의 길이를 a,b,c라고 할때…

  • a = |c – i1| = 구의 반지름값
  • b = |pc – c|
  • c = |pc – i1|

위에서 오직 길이 c만이 미지수이며, 길이 c는 다음처럼 계산할 수 있다.

 

c^2 = a^2 – b^2

그림을 통해 di1은 다음과 같음을 알수있다.

di1 = |pc – p| – c

앞서 계산한 di1은 편선의 시작점(p)가 구의 내부에 있지 않다고 가정한 것이다. 만약 p가 구 안쪽에 있다면 di1에 대한 계산은 아래처럼 달라진다.

di1 = |pc – p| + c

사용자 삽입 이미지
구의 중심점이 편선에 투영되지 않는 경우

구의 중심점이 편선에 투영되지 않는 경우, 편선의 시작점이 구의 외부에 위치한다면 편선과 구가 교차하지 않는다는 것이다. 반면에… 편선의 시작점 p와 구의 중심점 c까지의 거리가 구의 반지름과 작거나 같다면 교차점이 존재한다. 같다면 p 자체가 교차점이다.

편선의 시작점이 구의 내부에 위치한다면, 앞의 구의 중섬점이 편선에 투영되는 경우와 같은 방법을 적용하여 교차점을 구할 수 있다. 아래 그림을 살펴면…

사용자 삽입 이미지
pc에서 i1까지의 거리 계산은 앞에서 본 것과 동일하다. 거리를 dist로 놓고.. di1은 다음처럼 계산할 수 있다.

di1 = dist – | pc – p |

 

평면의 공식

이 글의 원문은 http://www.lighthouse3d.com/opengl/maths/index.php?planes

원문의 내용을 그대로 번역한 것이 아닌, 제가 이해하고 이해한 내용에 대해 내용을 추가하였으며 좀 더 쉽게 풀어서 다시 작성한 글입니다.

3차원 상에서 평면은 많은 방법으로 표현할 수 있습니다. 그러나 이 모든 방법들은 모두 평면 상에 존재하는 세개의 점을 알고 있다는 가정 아래서 표현이 됩니다. 여하튼….. 가장 일반적인 평면을 기술하는 수학적인 공식은 다음과 같습니다.

사용자 삽입 이미지
평면 상에 존재하는 점을 p0, p1, p2라고 하면, 계수 A, B, C와 D는 다음과 같은 절차로 계산됩니다.

  1. 벡터 v와 u를 구하며, 벡터 v = p1 – p0, u = p2 – p0이다.
  2. 벡터 n = v x u (v와 u의 외적)
  3. 벡터 n을 정규화(크기가 1인 단위벡터화)
  4. 벡터 n=(xn, yn, zn)이라고 한다면 계수 A=xn, B=yn, C=zn 임
  5. 계수 D를 구하기 위해 앞에서 제시한 평면의 공식을 D에 대해 전개. 즉, -D = Ax + By + Cz
  6. 평면 상의 점(예를 들어 p0)에 대해 위의 공식의 x, y, z에 값을 대입하여 D를 구함(이 값은 내적을 이용해 쉽게 구할 수 있음. 즉, D = -n ∙ p0)

사용자 삽입 이미지

어떤 점에서 평면까지의 거리와 그 의미

이 블로그의 포스팅된 글에 중에 이와 관련된 글이 있지만, 평면에 대한 공식을 알아보니.. 복습 차원에서 다시 한번 정리해 보겠습니다.

앞에서 평면 방정식의 계수를 구하는 방법을 이용해 얻은 평면의 공식 Ax + By + Cz + D = 0 이 있다고 할때, 이 평면과 어떤 점 r 사이의 거리는… 만약 r이 (xr, yr, zr)이라면 이 좌표를 위의 평면의 방정식에 대입하여 D에 대해 전개하여 구한 값에 대해 절대값을 취하면 됩니다. 즉, D = |Axr + Byr + Czr|이며 이는 내적의 공식을 이용해서 다음처럼 표현할 수 있습니다.

사용자 삽입 이미지
거리값이므로 D에 대해서 절대값을 취했는데, 그렇다면 이 부호의 의미는 무엇일까요? 먼저 D 값이 0이라면 r은 평면 상에 존재하는 점입니다. r이 양수라면 평면을 기준으로 벡터 n의 방향에 있는 공간상에 r이 존재하고 음수라면 그 반대 방향에 존재합니다.

평면상에 어떤 점을 투영

점 q를 평면 Ax + By + Cz + D = 0에 투영한 점은 q에서 가장 가까운 평면상의 점입니다. q에서 평면까지의 부호있는 거리(계수 D)를 dist라고 한다면… 평면상에 가장 가까운 점 p는 다음과 같습니다.

사용자 삽입 이미지
사용자 삽입 이미지

선에 대한 수학적 설명

선에 대한 수학적 표현인, 선에 대한 방정식은 좌표와 벡터로 설명될 수 있습니다. 어떤 선이 있다고 해 보면, 그 선이 점p를 지나고 선의 방향은 벡터v라고 한다면 아래 그림처럼 상상해 볼 수 있습니다.

사용자 삽입 이미지
아래의 공식은 선을 구성하는 좌표를 얻는데 사용할 수 있습니다.

사용자 삽입 이미지
t는 스칼라입니다. t값에 의해 선 상의 모든 좌표를 얻을 수 있습니다. t가 0이면 좌표 p가 얻어집니다. t가 0이 아닌 다른 값이면 선 상의 다른 좌표가 얻어집니다. 백터는 2개의 좌표로부터 생성되어지므로 v는 선을 지나는 2개의 좌표를 통해 얻어집니다. p이외에 선을 지나는 다른 한 점을 p1이라고 하면 v는 p1 – p가 됩니다.

선은 양쪽 방향으로 계속 이어지며 확장된다는 것이고 광선(Ray)은 한 방향으로만 계속 이어지며 확장된다는 것으로 정의할 수 있습니다.

사용자 삽입 이미지
위의 그림에서 상단은 선이고 하단은 광선입니다. 위의 공식을 통해 다시 살펴보면, 선과 광선의 차이점은 t가 가질수 있는 값의 범위가 다르다는 점입니다. 선에서 t는 제한이 없으며, 광선에서 t는 음수가 될 수 없습니다.

선과 어떤 좌표 사이의 최단 거리

어떤 좌표와 어떤 선 사이의 가장 짧은 거리는 그 좌표에서 그 선에 수직인, 선 상의 좌표로 구성되는 선분의 길이입니다. 좌표p와 백터v로부터 정의되는 선에 대해서 살펴보겠습니다. 어떤 좌표q에서 이 선(좌표p와 벡터v로 결정)까지의 거리를 계산하는 것이 목표입니다.

사용자 삽입 이미지
위의 그림은 좌표q에서 선까지의 거리가 좌표q와 좌표q’까지의 거리임을 보여줍니다. 좌표q’는 백터u를 백터v에 대해서 투영함으로써 얻어집니다. 백터간의 투영에 대해서는 이미 알고 있다고 가정하고 만약 모르신다면 이 블로그의 글을 참조하시길 바랍니다. 여하튼, 이 투영된 벡터 puv는 다음과 같습니다.

사용자 삽입 이미지
이제 q’는 아래처럼 정해질 수 있습니다.

사용자 삽입 이미지
이제 최단 거리는 q와 q’ 사이의 거리가 됩니다.

광선과 좌표 사이의 최단 거리

최단거리의 결과로 광선에 대해서 투영된 좌표들에 대해 동일한 결과 공식을 예상했으나, 다음 그림에서 보는 것처럼 항상 옳바르지는 않습니다.

사용자 삽입 이미지
앞서 어떤 좌표q와 선 사이의 거리를 위해 제시된 공식은 오직 광선 내에서 투영될 수 있을때만 의미가 있습니다. 백터u와 백터v에 대한 내적을 통해서 광선 내에서 투영되는지 검사할 수 있습니다. 즉, 백터 u와 v 사이의 코사인 각도가 음수라면 광선 내에서 투영되지 않는다는 것입니다. 코사인 각이 음수여서 광선에 투영되지 않는다면, 좌표q에서 그 광선까지의 최단 거리는 좌표q에서 광선의 시작점까지의 거리를 계산해서 쉽게 알 수 있습니다.

두 백터의 투영(Projection)

이 글의 목적은 백터v 위로 백터u를 투영하는 것에 대한 방법을 살펴보는 것입니다.

사용자 삽입 이미지
위 그림에서 백터puv는 백터v 위에 백터u를 투영한 것입니다. 그림에서 보면 알 수 있듯이, v와 puv는 평행하므로 puv는 다음처럼 정의될 수 있습니다. 물론 여기서 백터v는 크기가 1인 단위백터입니다.

사용자 삽입 이미지
여기서 |puv|는 puv의 길이입니다. |puv|를 알아내는 것이 곧 백터puv를 알아내는 것 입니다. 백터u와 백터puv의 길이 사이의 관계는 이 두 백터가 이루는 코사인 각입니다.

사용자 삽입 이미지
내적(Dot Product)의 정의는 다음과 같습니다.

사용자 삽입 이미지
위의 정의로부터, 백터puv의 길이는 다음과 같습니다.

사용자 삽입 이미지
결국, 이 글의 가장 처음에 언급한 공식으로부터 위의 식을 대입하면 다음과 같은 puv를 얻을 수 있습니다.

사용자 삽입 이미지