1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-30 19:50:01 +02:00

[ko-KR] Chapter 3 translation (#340)

* Automated build

* Automated build

* Translate chapter 3 into ko-KR

Co-authored-by: Bezierinfo CI <action@github.com>
This commit is contained in:
잇창명
2022-02-28 04:04:58 +09:00
committed by GitHub
parent bc1bffb8e6
commit ccf59ba778
19 changed files with 21976 additions and 50901 deletions

View File

@@ -0,0 +1,173 @@
# 베지에 곡선을 이루는 수학
베지에 곡선은 "매개변수" 함수의 일종입니다. 수학적으로 말하자면 매개변수 함수는 꼼수입니다. "함수"란 임의의 개수의 입력에서 <strong>하나의</strong> 출력으로 가는 대응을 의미하는, 엄연한 정의가 있는 용어입니다. 수를/수들을 넣으면 하나의 값이 나옵니다. 다른 수를 넣어도 값이 하나만 나오는 점은 변하지 않습니다.
매개변수 함수는 꼼수입니다. "저는 여러 값이 나오는 함수가 필요한데 그냥 함수를 여러 개 쓰면 안 돼요?"인 것이죠. 예컨대 어떤 값(<i>x</i>라고 합시다)을 어떤 연산을 통해 다른 값과 대응시키는 함수가 있다고 합시다.
\[
f(x) = \cos(x)
\]
<i>f(x)</i>라는 표기는 <i>f</i>(함수가 하나만 있을 때는 관습적으로 <i>f</i>를 씁니다)가 함수이며, 그 값이 하나의 변수(여기서는 <i>x</i>)에 따라 바뀜을 나타내는 표준적인 방법입니다. <i>x</i>를 바꾸면 <i>f(x)</i>의 값도 바뀝니다.
여기까지는 좋습니다. 이제 매개변수 함수를 보고, 어떤 꼼수를 쓰는지 확인해 봅시다. 아래의 두 함수를 생각해 봅시다.
\[
\begin{matrix}
f(a) = \cos(a) \\
f(b) = \sin(b)
\end{matrix}
\]
별 특이할 점이 없는 사인과 코사인 함수인데, 자세히 보면 두 입력이 다른 이름을 가지는 것을 확인할 수 있습니다. <i>a</i>의 값을 바꾸더라도 <i>f(b)</i>에서는 <i>a</i>를 쓰지 않으므로 <i>f(b)</i>의 값이 바뀌지는 않습니다. 바로 이 부분을 조금 고치는 것이 매개변수 함수의 꼼수입니다. 매개변수 함수에서는 아래와 같이 여러 가지 함수가 같은 변수를 공유합니다.
\[
\left \{ \begin{matrix}
f_a(t) = \cos(t) \\
f_b(t) = \sin(t)
\end{matrix} \right.
\]
함수는 여러 개인데 변수는 하나뿐이네요. <i>t</i>의 값을 바꾸면 <i>f<sub>a</sub>(t)</i><i>f<sub>b</sub>(t)</i>의 값이 모두 바뀝니다. 이게 어딜 봐서 유용한지 궁금해하는 독자가 있다면, 답은 의외로 간단합니다. <i>f<sub>a</sub>(t)</i><i>f<sub>b</sub>(t)</i>라는 이름표를 매개변수 곡선을 만들 때 보통 의미하는 바를 나타내도록 바꾸면 이 식이 눈에 더 잘 들어올지도 모르겠습니다.
\[
\left \{ \begin{matrix}
x = \cos(t) \\
y = \sin(t)
\end{matrix} \right.
\]
짜잔! <i>x</i>/<i>y</i>좌표가 어떤 미지의 값 <i>t</i>를 통해 이어져 있었습니다.
정리하자면, 매개변수 곡선은 보통의 함수처럼 <i>y</i>좌표를 <i>x</i>좌표값에 대해 정의하는 대신 두 값을 어떤 "조절" 변수로 연결합니다. <i>t</i>의 값을 바꿀 때마다 매개변수 함수에서 <strong></strong> 값을 얻을 수 있고, 이 값을 그래프에 (<i>x</i>,<i>y</i>) 좌표로 나타낼 수 있습니다. 예를 들어 위에서 소개한 매개변수 함수는 원 위의 점을 생성합니다. <i>t</i>의 값을 음의 무한대에서 양의 무한대까지 잡을 수 있고, 여기서 나오는 (<i>x</i>,<i>y</i>) 좌표는 항상 중심이 원점 (0,0)이고 반지름이 1인 원 위에 있습니다. <i>t</i>의 값 0부터 5까지에 대해 그래프를 그리면 다음과 같습니다.
<graphics-element title="원(의 일부): x=sin(t), y=cos(t)" src="./circle.js">
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control">
</graphics-element>
베지에 곡선은 여러 종류의 매개변수 함수 중 한 종류이고, 모든 출력값을 같은 기초 함수로 구합니다. 위에서 살펴본 예제에서는 <i>x</i><i>y</i> 값을 다른 함수로 구했지만(하나는 사인, 다른 하나는 코사인), 베지에 곡선은 <i>x</i>, <i>y</i> 값을 모두 "이항 다항식"으로 구합니다. 이항 다항식은 또 뭘까요?
중·고등학교에서 다항식을 배운 기억이 나시나요? 이렇게 생긴 합을 다항식이라고 합니다.
\[
f(x) = a \cdot x^3 + b \cdot x^2 + c \cdot x + d
\]
여기서 가장 높은 차수의 항이 <i></i>이면 3차( 다항)식, <i></i>이면 2차식이라 하고, <i>x</i>라면 1차식, 즉 직선이 됩니다. (혹시 <i>x</i>가 있는 항이 하나도 없다면 그건 애초에 다항식이 아니죠!)
베지에 곡선은 <i>x</i>가 아니라 <i>t</i>에 대한 다항식이고, <i>t</i>의 값이 0과 1 사이로 고정되며 <i>a</i>, <i>b</i> 등의 계수가 "이항계수"의 형태를 띱니다. 이항계수라고 하면 어려워 보이지만 사실은 두 값을 섞는 것을 간단하게 나타낸 것입니다.
\[
\begin{aligned}
\textit{1차} &= (1-t) + t \\
\textit{2차} &= (1-t)^2 + 2 \cdot (1-t) \cdot t + t^2 \\
\textit{3차} &= (1-t)^3 + 3 \cdot (1-t)^2 \cdot t + 3 \cdot (1-t) \cdot t^2 + t^3
\end{aligned}
\]
제가 한 말이긴 하지만 저 식이 딱히 간단해 보이지는 않죠! 그런데 여기서 <i>t</i>를 없애고 대신 "곱하기 1"을 넣으면, 복잡한 수식이 갑자기 간단하게 바뀝니다. 밑에 늘어놓은 이항계수를 보세요.
\[
\begin{aligned}
\textit{1차} &= \hspace{2.5em} 1 + 1 \\
\textit{2차} &= \hspace{1.7em} 1 + 2 + 1\\
\textit{3차} &= \hspace{0.85em} 1 + 3 + 3 + 1\\
\textit{4차} &= 1 + 4 + 6 + 4 + 1
\end{aligned}
\]
식을 잘 보면 2는 1+1과 같고, 3은 2+1과 1+2이고, 6은 3+3...이라는 것을 알 수 있습니다. 보신 바와 같이 한 차수가 높아질 때마다 양 끝은 1이고, 그 사이의 모든 수는 "윗줄에 있는 두 수를 더한 것"과 같으며, 이렇게 만들어진 모양을 [파스칼의 삼각형](https://ko.wikipedia.org/wiki/%ED%8C%8C%EC%8A%A4%EC%B9%BC%EC%9D%98_%EC%82%BC%EA%B0%81%ED%98%95)이라고 합니다. <i>이건</i> 기억하기 쉽죠?
다항식의 문자 부분도 쉽게 외울 수 있는 방법이 있습니다. <i>(1-t)</i><i>a</i>로, <i>t</i><i>b</i>로 바꾸고 계수를 잠깐 지우면 아래의 식을 얻습니다.
\[
\begin{aligned}
\textit{1차} &= BLUE[a] + RED[b] \\
\textit{2차} &= BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot RED[b] + RED[b] \cdot RED[b] \\
\textit{3차} &= BLUE[a] \cdot BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot BLUE[a] \cdot RED[b] + BLUE[a] \cdot RED[b] \cdot RED[b] + RED[b] \cdot RED[b] \cdot RED[b]\\
\end{aligned}
\]
이제 이 식은 "<i>a</i><i>b</i>의 모든 조합의 합"인데, + 부호가 나올 때마다 <i>a</i>가 하나씩 <i>b</i>로 바뀌는 것으로 외울 수 있습니다. 이쪽도 그렇게 어렵지 않았네요. 이것으로 이항 다항식을 모두 배웠고, 혹시 필요할 경우를 위해 아래에 일반항의 식을 추가합니다.
\[
\textit{Bézier}(n,t) = \sum_{i=0}^{n}
\underset{\textit{이항계수 부분}}{\underbrace{\binom{n}{i}}}
\cdot\
\underset{\textit{문자 부분}}{\underbrace{(1-t)^{n-i} \cdot t^{i}}}
\]
위 식으로 베지에 곡선을 완전히 기술할 수 있습니다. 이때 위 함수에서 Σ(시그마) 기호는 여러 개의 값을 더한다는 의미입니다(Σ 기호 밑에 적힌 문자를 ...=&lt;&gt;에서 시작해서 Σ 위에 적힌 값까지 바꿔가면서 더합니다).
<div class="howtocode">
### 기저 함수를 구현하는 방법
기저 함수를 구현할 때, 아래와 같이 위에서 본 수식을 그대로 함수로 옮겨서 구현할 수는 있습니다.
```
function Bezier(n,t):
sum = 0
for(k=0; k<n; k++):
sum += n!/(k!*(n-k)!) * (1-t)^(n-k) * t^(k)
return sum
```
구현할 "수는" 있다고 한 것은 이렇게 구현하지 않을 것이기 때문입니다. 계승 함수는 *매우* 무겁고, 위에서 배운 것과 같이 계승을 쓰지 않고도 파스칼의 삼각형은 쉽게 만들 수 있습니다. [1]부터 시작하고, 그 다음에는 [1,1], [1,2,1], [1,3,3,1]과 같은 식으로, 줄이 바뀔 때마다 수 하나를 더 넣고 양쪽 끝은 1로, 그 사이의 모든 수는 지금 계산하고 있는 줄 바로 위의 양쪽 원소의 합으로 채우면 됩니다.
위의 삼각형은 리스트의 리스트로 눈 깜짝할 새 구현할 수 있고, 이제 룩업 테이블을 만들었으니 이항계수는 다시 구할 필요도 없습니다.
```
lut = [ [1], // n=0
[1,1], // n=1
[1,2,1], // n=2
[1,3,3,1], // n=3
[1,4,6,4,1], // n=4
[1,5,10,10,5,1], // n=5
[1,6,15,20,15,6,1]] // n=6
function binomial(n,k):
while(n >= lut.length):
s = lut.length
nextRow = new array(size=s+1)
nextRow[0] = 1
for(i=1, prev=s-1; i<s; i++):
nextRow[i] = lut[prev][i-1] + lut[prev][i]
nextRow[s] = 1
lut.add(nextRow)
return lut[n][k]
```
코드를 해석해 볼까요? 우선 웬만한 <i>n/k</i> 값을 모두 다룰 수 있는 적당한 크기로 룩업 테이블을 선언합니다. 그 다음에는 필요한 값을 읽어오는 함수를 선언하고, 인자로 전달된 <i>n/k</i> 값이 테이블에 없으면 우선 테이블을 키우도록 합니다. 이제 기저 함수를 아래와 같이 구현할 수 있습니다.
```
function Bezier(n,t):
sum = 0
for(k=0; k<=n; k++):
sum += binomial(n,k) * (1-t)^(n-k) * t^(k)
return sum
```
좋습니다. 물론 여기에서도 최적화의 여지가 남아 있습니다. 대부분의 컴퓨터 그래픽 용도로는 임의 차수의 곡선이 필요 없습니다(물론 입문서에서는 임의 차수 곡선을 다루는 코드를 제공할 예정입니다). 보통 2차와 3차 곡선만 사용하기 때문에, 아래와 같이 훨씬 간단한 코드로 고칠 수 있습니다.
```
function Bezier(2,t):
t2 = t * t
mt = 1-t
mt2 = mt * mt
return mt2 + 2*mt*t + t2
function Bezier(3,t):
t2 = t * t
t3 = t2 * t
mt = 1-t
mt2 = mt * mt
mt3 = mt2 * mt
return mt3 + 3*mt2*t + 3*mt*t2 + t3
```
이제 기저 함수를 프로그래밍하는 법을 모두 배웠습니다. 와!
</div>
지금까지 베지에 곡선의 기저 함수를 살펴보았습니다. 이제 베지에 곡선을 그토록 특별하게 만드는 것, 조절점을 살펴볼 시간입니다.