문제 개요
하나의 원과 하나의 직선이 주어졌을 때, 그 직선이 원에 접하는지, 원을 교차(관통)하는지, 아니면 원의 바깥쪽을 지나가는지 판별하는 것이 이 글의 목표입니다. 직선과 원의 위치 관계는 크게 세 가지 경우로 나뉩니다.
- 직선이 원에 한 점에서 닿는 경우 (접선)
- 직선이 원을 두 점에서 통과하는 경우 (교차)
- 직선이 원과 만나지 않고 지나가는 경우 (외부)
판별 알고리즘
다음 두 단계만 거치면 손쉽게 판별할 수 있습니다.
- 원의 중심과 주어진 직선 사이의 수직 거리 P를 구합니다.
- 거리 P를 반지름 r과 비교합니다.
- P > r : 직선은 원의 바깥쪽을 지나갑니다.
- P = r : 직선은 원에 접합니다.
- P < r : 직선은 원과 교차합니다.
수직 거리 계산 공식
중심 좌표를 (h, k)라고 할 때, 점에서 직선 ax + by + c = 0까지의 수직 거리는 다음 공식으로 구합니다.
$$\frac{|ah+bk+c|}{\sqrt{a^2+b^2}}$$
C++ 구현 예제
#include <iostream>
#include <cmath>
using namespace std;
void isTouchOrIntersect(int a, int b, int c, int h, int k, int radius) {
double dist = abs(a * h + b * k + c) / sqrt((double)(a * a + b * b));
if (radius == dist)
cout << "Touching the circle" << endl;
else if (radius > dist)
cout << "Intersecting the circle" << endl;
else
cout << "Outside the circle" << endl;
}
int main() {
int radius = 5;
int h = 0, k = 0;
int a = 3, b = 4, c = 25;
isTouchOrIntersect(a, b, c, h, k, radius);
}
실행 결과
Touching the circle
동작 원리
예제에서 원의 중심은 (0, 0), 반지름은 5이며, 직선의 방정식은 3x + 4y + 25 = 0입니다. 중심에서 직선까지의 거리를 공식에 대입하면 |3×0 + 4×0 + 25| ÷ √(3² + 4²) = 25 ÷ 5 = 5가 되어 반지름과 정확히 일치합니다. 따라서 이 직선은 원에 한 점에서 닿는 접선임을 알 수 있습니다.
참고로 실제 프로젝트에서는 부동소수점 연산의 오차를 고려하여, 거리와 반지름을 ==로 직접 비교하기보다 작은 오차 범위(예: 1e-6)를 허용하는 방식으로 비교하는 것이 더 안전합니다.