점과 직선의 공식

함수

함수라는 용어는 개발자 친구들에게는 아주 익숙할 것이다.
수학에서의 정의도 프로그래밍 세계와 크게 다르지 않는데, 일반적으로 입력값을 넣으면 함수는 그 정보를 토대로 새로운 정보를 반환하는 일을 한다.

수학에서 함수는 일반적인 수를 다룬다. (프로그래밍에서 문자열등을 처리하는것과는 달리) 함수를 정의하는 방법에는 두 가지가 있다.

첫 번째는, 입력값에 상응하는 출력값으로 구성된 순서 쌍의 참조 테이블을 만드는 것이다.

x y
0 0
1 2
2 4
3 6
4 8

이렇게 참조 테이블을 만드는것은 매우 간단하고 빠른 방법이다.
프로그래밍에서도 복잡하고 느리지만 자주 사용되는 연산 결과들을 저런식으로 해시 테이블로 저장해두고 참조하면, 성능상의 이점이 있는것이 사실이다.

그러나, 이 방식에는 큰 문제가 있는데, 해당 참조 테이블에 존재하지 않는 값을 입력으로 사용하면, 결과를 알 수 없을 뿐만 아니라, 매우 다양한 케이스를 처리하게 하려면, 거대한 참조 테이블을 생성하여야 한다는 단점이 있다.

따라서, 두 번째 방법으로 위 함수를 y=2x 와 같이 정의할 수 있다.
이렇게 함수를 방정식으로 정의해 두면, x의 입력값에 대한 모든 y의 값을 알아낼 수 있다.

좌표계

이렇게 정의된 함수를 사용하면, 컴퓨터 화면에서 특정 위치를 표현하는데 사용할 수 있을 것이다.

먼저, 컴퓨터상의 화면 좌표계와 데카르트 좌표계(Cartesian Coordinate System)를 알아보자.

화면 좌표계와 데카르트 좌표계

왼쪽의 화면 좌표계는 우리가 흔하게 알고 있는 좌표계로써, 좌상단을 기준으로 아래로 향할 수록 y값이 증가하고, 오른쪽으로 갈 수록 x값이 증가한다.

그러나, 오른쪽의 데카르트 좌표계는 화면 좌표계와 유사하지만, 좌하단을 기준으로 위로 향할 수록 y값이 증가하고, 아래로 향하면, y값이 감소한다. 우리가 학생시절 교과 과정을 통해 배웠던 좌표계가 바로 이 데카르트 좌표계이며, WebGL과 같은 그래픽스 프로그래밍에서도 사용할 좌표계이다.

그래픽스 프로그래밍에서는 데카르트 좌표계 상에 모델을 배치하고 회전이나 이동과 같은 작업을 수행후 최종 렌더링 과정에서는 화면 좌표계로 변화해서 표시해야한다. (이 방법은 추후에 설명)

이와 같은 좌표계를 3차원으로 확장하는것도 마찬가지인데, 3번째 좌표계인 z축을 추가해보면 다음과 같다.

3차원 오른손 좌표계

각 엔진별로 좌표계를 사용하는 방식이 조금씩 틀린데, 어떤 시스템에서는 오른손 좌표계를, 어떤 시스템에서는 왼손 좌표계를 사용할 수도 있다.
위 그림은, 전형적인 오른손 좌표계를 표현한 것으로써, z축이 화면으로부터 관찰자 쪽으로 뻗어 나온다. 즉, 관찰자로 다가올 수록 z축의 값이 커진다.

왼손 좌표계와 오른손 좌표계. 이미지 출처: http://www.learnopengles.com/understanding-opengls-matrices/left_right_hand

우리는, 상향 y축을 갖는 오른손 좌표계를 사용할 것이다. 전통적인 수학 좌표계이며, OpenGL, WebGL에서 사용하는 좌표계이기 때문이다.

좌표계 위에서의 점은 (x, y)와 같이 기술할 수 있으며, 3차원에서는 z축을 추가하여 (x, y, z)로 표기한다.

점 A(7, 4), B(0, 8), C(-5, 0), D(-3, -7), E(6, -5) 에 대한 2차원 좌표 표기

직선의 정의

좌표계상의 점들을 직선으로 연결할 수 있다면, 이 점의 집합들을 이용해서 직선의 방정식을 정의할 수 있다.
직선의 방정식은 Ax + By = C 와 같이 정의한다.

Ax + By = C

직선의 방정식

글의 맨 앞에서 정의한 참조 테이블을 대입한 방정식 y = 2x 의 해집합을 좌표계상에 표시해보면 다음과 같다.
y = 2x의 해집합

y = 2x의 방정식의 경우 언뜻 보면 Ax + By = C의 꼴이 아닌것처럼 보이는데,
실제로는 2x - y = 0 과 같이 풀이해 볼 수 있다.
y = 3 과 같은 식도 마찬가지로, 0x + y = 3 과 같은 직선의 방정식이다.

이런 형태의 1차 방정식은, 좌표계상에 직선으로 표시할 수 있으므로, 해집합이 직선이 되는 직선의 방정식이라고 할 수 있다.

직선의 성질

기울기

두점 P와 Q가 존재한다고 가정했을때, 두 점을 이어서 직선으로 만들면, 직선의 기울기를 정의할 수 있다.
기울기는 경사도라고도 하며, 직선의 이동량(x축의 변위)에 대한 상승량(y축의 변위)의 비율, 즉 상승량/이동량 이다.

예를 들어, P(0, 0)이고 Q(2, 1)일때 이동량은 2, 상승량은 1이며, x축이 2만큼 이동할 동안 y축은 1만큼 이동하였고 이동량에 대한 상승량의 비율인 1/2이 직선의 기울기이다.

기울기 m = (y2 - y1) / (x2 - x1)

기울기 공식

위 공식을 사용하여 기울기를 구하려면, 특정 직선의 방정식으로 부터 임의의 두 점을 구한 다음, 이동량과 상승량을 구해야한다.
그러나, 직선의 방정식이 Ax + By = C 형태의 표준형이라면, 아래와 같이 간단한 계산법을 사용하여 기울기를 구할 수 있다.

m = -A/B

Ax + By = C로 정의된 직선의 기울기 m

직선의 기울기에는 다음과 같은 정보가 숨어 있다.

  • 기울기가 음수이면, 그래프는 왼쪽에서 오른쪽으로 갈수록 내려간다. (\ 형태)
  • 기울기가 양수이면, 그래프는 왼쪽에서 오른쪽으로 갈수록 올라간다. (/ 형태)
  • 기울기가 0이면, 그래프는 수평이다. (- 형태)
  • 기울기 공식 m = (y2 - y1) / (x2 - x1) 에서 제수(x2 - x1)가 0이면,
    기울기는 정의할 수 없고 그래프는 수직선이다.

두 직선과 각 직선의 기울기가 있을때는 다음과 같은 사실이 성립한다.

  • 두 직선의 기울기가 같으면, 두 직선은 평행하다. (교점이 없다.)
  • 두 직선이 직교(수직선으로 만날때)할때, 두 직선의 기울기를 곱하면 -1이된다.

    m1m2 = -1 또는
    m1 = -1/m2 또는
    m2 = -1/m1

    서로 직교하는 두 직선의 기울기 m1과 m2의 관계

기울기를 사용하면, 표준형 직선의 방정식 이외에 프로그래밍적으로도 유용한 두가지 다른 표현 방법을 적용할 수 있다.

y = mx + b

기울기-절편 공식. b는 y절편

기울기-절편 공식은 y의 결과 값이 식의 나머지 부분으로 결정되기 때문에, 프로그래밍 코드로 방정식을 구현하기가 용이하다.
y의 절편 b는 그래프 상에서 직선이 y축과 교차하는 지점으로써 x가 0일때의 y 값이다. 반대로 x의 절편은 y가 0일때의 x 값이다.

(y - y1) = m(x - x1)

점-기울기 공식. x1과 y1은 직선 위의 한 점

점-기울기 공식으로 표현하면, 두 점만 가지고도 직선의 방정식을 도출해낼 수 있게된다.
예를 들어, 현재 위치와 목표 위치를 알고 있지만, 직선의 방정식을 알고 있지 않다면, 이 공식을 적용해 볼 수 있다.

케릭터가 점 S(50, 200)에서 E(150, 400)로 움직이는 직선에 대한 방정식을 구하는 단계는 다음과 같다.

  1. x와 y의 변위를 이용하여 기울기를 구한다.
    기울기 = m = (Ye - Ys) / (Xe - Xs) = (400 - 200) / (150 - 50) = 200 / 100 = 2
  2. 점-기울기 공식에 임의의 점을 대입한다.
    (y - y1) = m(x - x1)
    점 E(150, 400)를 대입
    (y - 400) = 2(x - 150)
    y - 400 = 2x - 300
    y = 2x + 100

점-기울기 공식을 이용하여, 기울기-절편 공식 형태로 직선의 방정식을 구했다.
코드로 표현하기 위해, x좌표에 대응하는 y의 값을 알아낼때는 기울기-절편 공식이 유리하다.
기울기-절편 공식은 표준형 직선의 방정식처럼 이미 만들어진 방정식을 사용하기 간편하게 해주며, 점-기울기 공식은 점과 기울기를 이용해 이런 방벙식을 유도하기 쉽게 해준다.

이제, 위에서 알아본 직선의 방정식과 기울기 공식들을 응용하면, 직선 운동을 하는 물체의 방정식으로 부터 직교하는 다른 직선의 방정식을 구할 수 있다.
한 물체가 y = 2/3x + 20을 따라서 움직이고 있다고 가정하자. 이 물체가 (30, 40)의 위치에서 왼쪽 90도 방향으로 꺾은 직선 방향으로 가도록 하고자 할때, 꺾은 후의 이동 경로에 대한 방정식은 다음과 같이 유도할 수 있다.

  1. y = 2/3x + 20기울기-절편 형태의 방정식이므로 기울기 m = 2/3이다.
  2. 기울기 m = 2/3과 직교하는 새 직선의 기울기 m2-1/m 이므로 m2 = -3/2 가 된다.
  3. 점 (30, 40)도 새 직선상의 한 점이므로 2번에서 알아낸 기울기를 사용해 점-기울기 공식에 대입한다.
    (y - y1) = m(x - x1)
    (y - 40) = -3/2(x - 30)
    (y - 40) = -3/2x + 45
  4. 3번의 식을 기울기-절편 공식으로 변환한다.
    y = -3/2x + 85

그림으로 표현하면 다음과 같다.
(30, 40) 지점에서 y = 2/3x + 20 과 직교하는 직선 y = -3/2x + 85

3차원에서의 직선도 2차원과 크게 다르지 않다. 단지 z축이 추가되었을 뿐이다. 여기서는 단순하게 좌표와 직선의 공식을 통해서 표현하고 있지만, 차후에는 벡터를 다루어 직선과 좌표를 표현할 것이다.
2차원 직선을 벡터로 표기하면 점은 <x, y> 또는 <30, 40>의 형태, 기울기는 <∆x, ∆y> 또는 <2, -3>의 형태로 표기한다. 3차원에서는 점 <x, y, z>와 기울기 <∆x, ∆y, ∆z>로 표기하면 된다.

따라서, 3차원상의 점 <50, 200, 75>에서 <100, 50, 225>로 이동했다고 가정하면, 두 점의 기울기는 다음과 같이 구할 수 있다.

∆x = 100 - 50 = 50
∆y = 50 - 200 = -150
∆z = 225 - 75 = 150
위치의 변화량(변위)는 <50, -150, 150>

직선의 성질을 이용한 충돌 검사

그래픽스 프로그래밍을 하다보면, 두 물체의 이동경로상에서 충돌지점을 알아야할 경우가 있을 것이다.
즉, 두 직선의 방정식의 교점을 구하면 된다. 그러나, 두 직선이 충돌한다면 충돌 지점은 하나겠지만, 두 직선이 평행하다면 영원히 충돌하지 않을 것이다. 따라서, 직선의 성질을 이용해서 충돌지점의 개수를 먼저 파악해보는것이 예외상황을 보다 빨리 예측할 수 있을것이다.

각 직선의 방정식이 정의되어 있다고 한다면, 기울기-절편 공식을 통해 기울기와 y절편으로 다음과 같이 충돌지점의 개수를 예측할 수 있다.

  • 두 직선의 기울기가 서로 다르면, 충돌지점은 하나
  • 두 직선의 기울기와 y절편이 모두 같으면, 충돌지점은 무한
  • 두 직선의 기울기는 같으나, y절편이 다르면, 충돌지점은 없음

이런, 두 직선의 관계는 1차 연립방정식을 통해 정의되며, 정확한 충돌지점 또한 알아낼 수 있다.

두 직선의 충돌지점 알아내기

두 직선의 교차점. 즉, 충돌지점을 알아내는데는 두 가지 방법을 사용할 수 있다.

  • 선형결합법
  • 치환법

미지수가 2개인 연립방정식의 해를 구하는 방법이다.

선형결합법

선형결합법은 등식의 성질을 이용하여 연립방정식을 풀기 편하게 변환하는 방법이다. 방정식의 양변에 0이 아닌 같은 수를 곱해서, 두 방정식의 x나 y의 계수가 같아지도록 만드는 방법이다.
다음과 같은 두 방정식을 살펴보자.

3x + 2y = 10
4x + 3y = 6

위 두 방정식에서 특정 미지수의 계수가 같아지도록 공배수를 곱해서, 계수가 같아지도록 만들어 보자. 여기서는 y의 계수를 일치 시켜보았다.

3(3x) + 3(2y) = 3(10)
2(4x) + 2(3y) = 2(6)

이렇게 양변을 곱해주면, y의 계수가 6으로 같아진다.

9x + 6y = 30
8x + 6y = 12

이제, 위 두개의 방정식을 결합한다. 단순히 한 방정식을 다른 방정식에서 빼주면 된다.
9x + 6y = 30
-(8x + 6y = 12)
x + 0y = 18
x = 18

교점의 x좌표를 구했으니, 두 방정식 중 하나에 대입하면 y의 좌표도 구할 수 있다.
3x + 2y = 10
3(18) + 2y = 10
54 + 2y = 10
y = -22

결과적으로, 이 연립방정식의 해는 (18, -22)이며 두 직선의 충돌지점(교점)이다.

위 단계를 요약해보면 다음과 같다.

  1. x, y중에서 소거할 변수 선택
  2. 소거할 변수의 계수가 같아지도록 공배수를 곱한다.
  3. 한 방정식에서 다른 방정식을 빼서 연립방정식의 선형 결합을 구한다.
  4. 첫 번째 변수의 값을 구한다.
  5. 첫 번째 변수의 값을 방정식에 대입하여 나머지 변수의 값을 구한다.

치환법

치환법은 좀 더 일반적인 연립방정식의 풀이법이다.
이 방식은 주어진 두 방정식중 하나를 하나의 변수에 대해서 정리한 다음, 나머지 방정식에 대입한다.
다음과 같은 두 방정식을 살펴보자.

x + 2y = 5
3x - 2y = -1

첫 번째 방정식을 x에 대해 정리하면, 다음과 같다.
x + 2y = 5
x = -2y + 5

x에 대해 정리된 첫 번째 방정식을 나머지 방정식의 x와 치환한다.
3x - 2y = -1
3(-2y + 5) - 2y = -1
-6y + 15 - 2y = -1
-8y = -16
y = 2

교점의 y좌표를 구했으니, 두 방정식 중 하나에 대입하면 x의 좌표도 구할 수 있다.
x + 2y = x + 2(2) = 5
x + 4 = 5
x = 1

이 연립방정식의 해는 (1, 2)이며 두 직선의 충돌지점(교점)이 구해졌다.

위 단계를 요약해보면 다음과 같다.

  1. 두 방정식 중 하나를 골라, 변수 하나에 대해 정리한다.
  2. 정리한 등식을 다른 방정식에 치환한다. (이 때, 1번 단계에서 선택된 변수가 소거된다.)
  3. 남은 변수에 대한 방정식의 답을 구한다.
  4. 3단계에서 구해진 답을 두 방정식 중 하나에 대입하여, 나머지 변수를 구한다.

충돌지점 알아내기에 대한 결론

선형결합법과 치환법 모두 한개의 해를 가지는 임의의 1차 연립방정식을 푸는데 사용할 수 있다.
두 방정식 중 어느 한 변수의 계수가 1이라면, 치환법이 해룰 구하는데 유리하며, 그렇지 않다면 선형결합법을 사용하는것이 좋다.

이제, 이것을 코드로 풀어봐야할 차례이다.
먼저, 두 직선을 점-기울기 공식으로 정의해보자. 두 직선이 교차하므로, x와 y는 두 직선의 교점이된다.

y - y1 = m1(x - x1)
y - y2 = m2(x - x2)

그런 다음, 두 식을 y에 대해 정리한다.

y = m1(x - x1) + y1
y = m2(x - x2) + y2

y가 두 직선의 교점 이므로, 위 식은 등식이된다.

m1(x - x1) + y1 = m2(x - x2) + y2

이제, x에 대해 정리하면 최종적으로 다음과 같은 식이 유도된다.

m1x - m1x1 + y1 = m2x - m2x2 + y2
m1x - m2x = m1x1 - m2x2 + y2 - y1
x(m1 - m2) = m1x1 - m2x2 + y2 - y1

x = (m1x1 - m2x2 + y2 - y1) / (m1 - m2)

이제, 각 직선을 특정 좌표와 기울기로 정의하여 충돌지점을 알아내는 자바스크립트 함수 코드를 살펴보자.
어렵지 않은 코드이니 위의 공식을 대입하여 생각해보자.

점1과 기울기1, 점2와 기울기2를 통해 충돌지점을 알아내는 함수
/**
 * point1, point2 는 x와 y를 가지는 좌표 객체 1,2
 * slope1, slope2 는 Number 타입의 기울기 1,2
 */
function getLineIntersect(point1, slope1, point2, slope2) {
    var intersectX = 0,
        intersectY = 0;

    // x = (m1x1 - m2x2 + y2 - y1) / (m1 - m2)
    intersectX = ((slope1 * point1.x) - (slope2 * point2.x) + point2.y - point1.y)
                / (slope1 - slope2);
    // y = m1(x - x1) + y1
    intersectY = slope1 * (intersectX - point1.x) + point1.y;

    return {
        x: intersectX,
        y: intersectY
    };
}

다음 글에서는, 그래픽스 프로그래밍에서 필요한 기하학적 기초에 대해 설명하도록 하겠다.
기하학적 기초에는 점 사이의 거리, 포물선, 원과 구, 원과 원, 구와 구의 충돌 검출 응용 등에 대해 다룬다.