Logo hyuki.dev
MATLAB으로 원형 패턴을 그리는 WanderCircle 함수 만들기

MATLAB으로 원형 패턴을 그리는 WanderCircle 함수 만들기

2025.05.20
5 min read
Table of Contents

안녕하세요 !
오늘은 MATLAB에서 아름다운 원형 패턴을 쉽게 만들 수 있는 WanderCircle 함수를 소개합니다 !

📌 WanderCircle 함수의 기능

WanderCircle 함수는 서로 접하는 다양한 크기의 원들을 랜덤하게 생성하여 시각적으로 흥미로운 패턴을 만듭니다. 각 원은 이전 원과 정확히 한 점에서 접하며, 무작위 색상으로 표현됩니다.
수학적으로는 원의 접선 개념을 활용한 알고리즘입니다.

🔍 원의 접선 개념

원의 접선 관계 다이어그램

WanderCircle 함수의 핵심은 원과 원이 접하는 성질을 이용하였습니다 !
원의 접선에 대한 기본 개념을 살펴보겠습니다.

원의 접선의 기본 성질

원의 접선은 접점을 지나는 반지름에 수직입니다.

따라서, 원의 중심에서 접점까지 연결한 선(반지름)은 그 점에서의 접선과 항상 직각을 이룹니다.

두 원의 접촉

두 원이 서로 접할 때, 두 원의 중심 사이의 거리는 두 반지름의 합과 같습니다 (외접).
이는 WanderCircle 함수에서 다음 원의 중심 위치를 계산하는 핵심 원리입니다 !

x0(k+1) = x0(k) + x(p(k)) * (r(k) + r(k+1))

(새 원의 중심 = 현재 원의 중심 + 방향벡터 × (두 반지름의 합))

원과 직선의 위치 관계

원의 중심에서 직선까지의 거리(d)와 원의 반지름(r)의 관계로 판단합니다.

  • d > r: 원과 직선은 만나지 않음
  • d = r: 원과 직선은 한 점에서 만남
  • d < r: 원과 직선은 두 점에서 만남

💻 코드 구현

WanderCircle.m
function WanderCircle(n, t)
if nargin < 1
n = 100;
end
if nargin < 2
t = 2;
end
figure;
th = linspace(0, 2*pi, 100);
r = randi([1, 5], n+1, 1);
p = randi([1, length(th)], n, 1);
x0 = zeros(n+1, 1);
y0 = zeros(n+1, 1);
x = cos(th);
y = sin(th);
axis square;
axis off;
hold on;
for k = 1:n
current_x = x * r(k) + x0(k);
current_y = y * r(k) + y0(k);
plot(current_x, current_y, 'LineWidth', t, 'Color', rand(1,3));
next_center_x = x(p(k)) * (r(k) + r(k+1));
next_center_y = y(p(k)) * (r(k) + r(k+1));
x0(k+1) = x0(k) + next_center_x;
y0(k+1) = y0(k) + next_center_y;
end
hold off;
end

📊 코드 실행 결과

WanderCircle(100, 2)

WanderCircle(100, 2)

WanderCircle(50, 5)

WanderCircle(50, 5)

🔍 코드 설명

1. 함수 정의하기

function WanderCircle(n, t)

n개의 원을 t의 굵기로 설정하는 함수 정의!

2. 입력값 기본 설정하기

if nargin < 1
n = 100; % 기본 원 갯수: 100개
t = 2; % 기본 원 두께: 2
end
if nargin < 2
t = 2;
end

만약 입력인수가 1보다 작으면 입력 인수가 없는 WanderCircle() 형태인데
그떄 n을 100으로, t를 2로 설정!

그리고 만약 입력인수가 2보다 작으면 WanderCircle(n) 형태이고,
그때는 t를 2로 설정!

3. 그림 생성

figure;

새로운 그림 창을 생성!

4. 원을 그리기 위한 데이터 준비

th = linspace(0, 2*pi, 100);
r = randi([1, 5], n+1, 1); % 1~5 사이 랜덤 반지름
p = randi([1, length(th)], n, 1); % 랜덤 접점 위치
  • th는 원을 그리기 위한 각도값으로, 0에서 2π까지 100개의 점을 생성 !
  • r은 각 원 반지름인데, 1부터 5까지의 랜덤값을 n+1개 생성 !
  • p는 다음 원이 현재 원과 만나는 접점의 위치를 랜덤하게 생성 !
  • 공식문서: linspace에 대한 설명
  • 공식문서: randi에 대한 설명

5. 원 중심 초기화

x0 = zeros(n+1, 1);
y0 = zeros(n+1, 1);

모든 원의 중심점 좌표를 저장할 배열을 만들고 0으로 초기화 !
첫 번째 원은 (0,0)에 위치 !

6. 단위원 좌표 계산

x = cos(th);
y = sin(th);

단위원(반지름 1인 원)의 x, y 좌표를 계산 !
이 좌표들에 반지름을 곱하면 원하는 크기의 원을 그릴 수 있어요 !

7. 그래프 설정

axis square;
axis off;
hold on;
  • axis square: 그래프의 x축과 y축 비율을 1:1로 만들어서 원이 찌그러지지 않게 합니다 !
  • axis off: 좌표축과 눈금을 숨겨서 깔끔하게 만들어줍니다 !
  • hold on: 여러 원을 하나의 그래프에 계속해서 그릴 수 있게 해줍니다 !

8. 각 원 그리기

for k = 1:n

1부터 n까지 반복하면서 n개의 원을 생성 !

8-1. 현재 원 그리기
current_x = x * r(k) + x0(k);
current_y = y * r(k) + y0(k);
plot(current_x, current_y, 'LineWidth', t, 'Color', rand(1,3));

current_xcurrent_y는 현재 원의 x, y 좌표 !

단위원 좌표(x, y)에 반지름 r(k)를 곱하고, 원의 중심점(x0(k), y0(k))을 더해서 계산해요 !

plot 함수로 원을 그리고, 선의 굵기는 t, 색상은 랜덤으로 설정합니다 !

8-2. 다음 원 중심 계산
next_center_x = x(p(k)) * (r(k) + r(k+1));
next_center_y = y(p(k)) * (r(k) + r(k+1));
x0(k+1) = x0(k) + next_center_x;
y0(k+1) = y0(k) + next_center_y;

p(k)는 현재 원의 어느 점에서 다음 원이 접할지 결정하는 인덱스이에요 !
따라서 x(p(k))와 y(p(k)) 는 그 접점의 방향을 나타내는 단위벡터의 성분이에요.

두 원이 접하려면 중심 사이의 거리가 두 반지름의 합이 되어야 해요.
그래서 (r(k) + r(k+1))을 곱해서 적절한 거리를 계산합니다 !

최종적으로 현재 원의 중심(x0(k), y0(k))에서 계산된 거리만큼 이동한 위치가
다음 원의 중심(x0(k+1), y0(k+1))이 됩니다.