Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python으로 점들이 볼록 껍질(Convex Hull)을 형성하는지 확인하는 방법

볼록 껍질(Convex Hull) 판별 문제란?

다각형의 외곽 점들이 시계 방향 순서로 주어져 있을 때, 이 점들이 볼록 껍질(convex hull)을 형성하는지 확인하는 문제입니다.

Python으로 점들이 볼록 껍질(Convex Hull)을 형성하는지 확인하는 방법

위 그림에서 알 수 있듯이, 볼록 껍질을 이루는 다각형은 연속된 세 점이 만드는 내부 각도가 항상 180° 이하라는 중요한 성질을 가집니다. 따라서 모든 연속된 세 점에 대해 각도를 검사했을 때 180°를 초과하는 경우가 하나라도 없다면, 해당 다각형은 볼록 껍질이라고 판단할 수 있습니다.

예를 들어 입력이 points = [(3,4), (4,7), (7,8), (11,6), (12,3), (10,1), (5,2)]라면 출력은 True가 됩니다.

문제 해결 접근 방식

다음 단계에 따라 문제를 해결할 수 있습니다.

  • 점 목록의 길이를 n으로 설정합니다.
  • i를 0부터 점 개수까지 반복하면서 다음 작업을 수행합니다.
    • p1, p2, p3를 각각 points[i-2], points[i-1], points[i]로 지정합니다. 파이썬의 음수 인덱싱 덕분에 시작 지점에서 자동으로 마지막 점들로 순환(wrap-around)됩니다.
    • 세 점 (p1, p2, p3)이 이루는 각도가 180°보다 크면 False를 반환합니다.
  • 모든 검사를 통과하면 True를 반환합니다.

구현 예제

아래 코드를 통해 더 자세히 이해해 보겠습니다.

import math

def get_angle(a, b, c):
    angle = math.degrees(math.atan2(c[1]-b[1], c[0]-b[0]) - math.atan2(a[1]-b[1], a[0]-b[0]))
    return angle + 360 if angle < 0 else angle

def solve(points):
    n = len(points)
    for i in range(len(points)):
        p1 = points[i-2]
        p2 = points[i-1]
        p3 = points[i]
        if get_angle(p1, p2, p3) > 180:
            return False
    return True

points = [(3,4), (4,7), (7,8), (11,6), (12,3), (10,1), (5,2)]
print(solve(points))

입력

[(3,4), (4,7), (7,8), (11,6), (12,3), (10,1), (5,2)]

출력

True

코드 동작 원리

get_angle 함수는 점 a, b, c가 주어졌을 때 b를 꼭짓점으로 하는 두 벡터 ba와 bc 사이의 각도를 계산합니다. math.atan2를 사용해 각 벡터의 방위각을 구한 뒤 그 차이를 도(degree) 단위로 변환하고, 결과가 음수이면 360을 더해 0~360° 범위의 값으로 정규화합니다.

solve 함수는 시계 방향으로 배열된 점들을 순회하면서 연속된 세 점의 각도를 검사합니다. 각도가 180°를 초과하는 지점이 존재하면 오목한 부분이 있다는 의미이므로 False를 반환하고, 끝까지 통과하면 True를 반환합니다.

점의 개수를 n이라 할 때 각 점마다 상수 시간의 각도 계산만 수행하면 되므로, 전체 시간 복잡도는 O(n)으로 매우 효율적입니다.