에듀테크 프로젝트 대시보드
보로노이 다이어그램
캔버스를 클릭해 시드를 추가하자. 클릭할 때마다 모든 픽셀이 "누가 제일 가까운가"를 다시 계산해 색을 칠한다. 거리 재는 방식(유클리드 / 맨해튼)을 바꾸면 경계 모양이 확 달라진다.
시드 0개 · 픽셀 판정 0회 · 렌더 0 ms
시드 A와 B만 있다고 하자. 어떤 점 P가 셀 A에 속하려면 dist(P, A) < dist(P, B).
등호가 성립하는 점들 dist(P, A) = dist(P, B)은 정확히 A와 B를 잇는 선분의 수직 이등분선이다.
그 선을 기준으로 A쪽 반평면 전체가 셀 A가 된다.
시드가 여러 개면, 시드 A의 셀은 "A와 다른 모든 시드 사이의 수직 이등분선"이 만드는 반평면들을 전부 교집합한 것이다. 반평면의 교집합이므로 각 보로노이 셀은 항상 볼록 다각형 (경계 셀은 무한히 뻗는 볼록 영역)이다.
| 방법 | 아이디어 | 시간복잡도 |
|---|---|---|
| 브루트포스 (이 데모) | 모든 픽셀마다 가장 가까운 시드를 선형 탐색 | O(픽셀 수 × n) |
| 포춘의 스윕라인 | 수평선을 위→아래로 쓸며 포물선(beach line) 관리, 이벤트 처리 | O(n log n) |
| 델로네의 쌍대 | 델로네 삼각분할을 만든 뒤 각 삼각형의 외심을 연결 | O(n log n) |
화면에 색을 칠하는 용도라면 브루트포스(또는 GPU에서 "제프리 콘" 기법)로 충분하다. 하지만 셀의 실제 다각형 좌표가 필요하면 포춘 알고리즘이나 델로네 쌍대를 쓴다.
# 브루트포스: 픽셀 하나가 어느 셀인지 def owner(px, py, sites): best, bi = float('inf'), -1 for i, (sx, sy) in enumerate(sites): d = (px - sx)**2 + (py - sy)**2 # sqrt 불필요: 대소만 비교 if d < best: best, bi = d, i return bi
위 데모에서 "델로네 삼각분할"을 켜면 시드들을 삼각형으로 잇는 그물이 나타난다. 보로노이 다이어그램과 델로네 삼각분할은 같은 정보의 앞뒷면(쌍대, dual)이다.
델로네 삼각분할의 핵심 성질: 어떤 삼각형의 외접원 안에도 다른 점이 들어가지 않는다 (empty circumcircle). 덕분에 지나치게 가늘고 긴 삼각형이 잘 안 생겨서, 지형 메시·유한요소 해석의 기본 삼각화로 쓰인다.