mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-02-24 17:42:43 +01:00
ja-JP section 3
This commit is contained in:
parent
6ec56dbe85
commit
acd6710a75
File diff suppressed because one or more lines are too long
@ -70,48 +70,49 @@ Given \left (
|
||||
|
||||
},
|
||||
"explanation": {
|
||||
"locale": "en-GB",
|
||||
"title": "The mathematics of Bézier curves",
|
||||
"locale": "ja-JP",
|
||||
"title": "ベジエ曲線の数学",
|
||||
"getContent": function(handler) { return <section>
|
||||
<SectionHeader name="explanation" title="The mathematics of Bézier curves" number="3"/>
|
||||
<p>Bézier curves are a form of "parametric" function. Mathematically speaking, parametric functions are cheats: a "function" is actually a well defined term representing a mapping from any number of inputs to a <strong>single</strong> output. Numbers go in, a single number comes out. Change the numbers that go in, and the number that comes out is still a single number. Parametric functions cheat. They basically say "alright, well, we want multiple values coming out, so we'll just use more than one function". An illustration: Let's say we have a function that maps some value, let's call it <i>x</i>, to some other value, using some kind of number manipulation:</p>
|
||||
<SectionHeader name="explanation" title="ベジエ曲線の数学" number="3"/>
|
||||
<p>ベジエ曲線は「パラメトリック」関数の一種です。数学的に言えば、パラメトリック関数というのはインチキです。というのも、「関数」はきっちり定義された用語であり、いくつかの入力を<strong>1つ</strong>の出力に対応させる写像を表すものだからです。いくつかの数値を入れると、1つの数値が出てきます。入れる数値が変わっても、出てくる数値はやはり1つだけです。パラメトリック関数はインチキです。基本的には「じゃあわかった、値を複数個出したいから、関数を複数個使うことにするよ」ということです。例として、ある値<i>x</i>に何らかの操作を行い、別の値へと写す関数があるとします。</p>
|
||||
\[
|
||||
f(x) = \cos(x)
|
||||
\]<p>The notation <i>f(x)</i> is the standard way to show that it's a function (by convention called <i>f</i> if we're only listing one) and its output changes based on one variable (in this case, <i>x</i>). Change <i>x</i>, and the output for <i>f(x)</i> changes.</p>
|
||||
<p>So far so good. Now, let's look at parametric functions, and how they cheat. Let's take the following two functions:</p>
|
||||
\]<p>
|
||||
<i>f(x)</i>という記法は、これが関数(1つしかない場合は慣習的に<i>f</i>と呼びます)であり、その出力が1つの変数(この場合は<i>x</i>です)に応じて変化する、ということを示す標準的な方法です。<i>x</i>を変化させると、<i>f(x)</i>の出力が変化します。</p>
|
||||
<p>ここまでは順調です。では、パラメトリック関数について、これがどうインチキなのかを見てみましょう。以下の2つの関数を考えます。</p>
|
||||
\[
|
||||
\begin{matrix}
|
||||
f(a) = \cos(a) \\
|
||||
f(b) = \sin(b)
|
||||
\end{matrix}
|
||||
\]<p>There's nothing really remarkable about them, they're just a sine and cosine function, but you'll notice the inputs have different names. If we change the value for <i>a</i>, we're not going to change the output value for <i>f(b)</i>, since <i>a</i> isn't used in that function. Parametric functions cheat by changing that. In a parametric function all the different functions share a variable, like this:</p>
|
||||
\]<p>注目すべき箇所は特に何もありません。ただの正弦関数と余弦関数です。ただし、入力が別々の名前になっていることに気づくでしょう。仮に<i>a</i>の値を変えたとしても、<i>f(b)</i>の出力の値は変わらないはずです。なぜなら、こちらの関数には<i>a</i>は使われていないからです。パラメトリック関数は、これを変えてしまうのでインチキなのです。パラメトリック関数においては、どの関数も変数を共有しています。例えば、</p>
|
||||
\[
|
||||
\left \{ \begin{matrix}
|
||||
f_a(t) = \cos(t) \\
|
||||
f_b(t) = \sin(t)
|
||||
\end{matrix} \right.
|
||||
\]<p>Multiple functions, but only one variable. If we change the value for <i>t</i>, we change the outcome of both <i>f<sub>a</sub>(t)</i> and <i>f<sub>b</sub>(t)</i>. You might wonder how that's useful, and the answer is actually pretty simple: if we change the labels <i>f<sub>a</sub>(t)</i> and <i>f<sub>b</sub>(t)</i> with what we usually mean with them for parametric curves, things might be a lot more obvious:</p>
|
||||
\]<p>複数の関数がありますが、変数は1つだけです。<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>のラベルを、パラメトリック曲線の表示によく使われているもので置き換えてやれば、ぐっとはっきりするかと思います。</p>
|
||||
\[
|
||||
\left \{ \begin{matrix}
|
||||
x = \cos(t) \\
|
||||
y = \sin(t)
|
||||
\end{matrix} \right.
|
||||
\]<p>There we go. <i>x</i>/<i>y</i> coordinates, linked through some mystery value <i>t</i>.</p>
|
||||
<p>So, parametric curves don't define a <i>y</i> coordinate in terms of an <i>x</i> coordinate, like normal functions do, but they instead link the values to a "control" variable. If we vary the value of <i>t</i>, then with every change we get <strong>two</strong> values, which we can use as (<i>x</i>,<i>y</i>) coordinates in a graph. The above set of functions, for instance, generates points on a circle: We can range <i>t</i> from negative to positive infinity, and the resulting (<i>x</i>,<i>y</i>) coordinates will always lie on a circle with radius 1 around the origin (0,0). If we plot it for <i>t</i> from 0 to 5, we get this (use your up and down arrow keys to change the plot end value):</p>
|
||||
<Graphic preset="empty" title="A (partial) circle: x=sin(t), y=cos(t)" static={true} setup={handler.setup} draw={handler.draw} onKeyDown={handler.props.onKeyDown}/>
|
||||
<p>Bézier curves are (one in many classes of) parametric functions, and are characterised by using the same base function for all its dimensions. Unlike the above example, where the <i>x</i> and <i>y</i> values use different functions (one uses a sine, the other a cosine), Bézier curves use the "binomial polynomial" for both <i>x</i> and <i>y</i>. So what are binomial polynomials?</p>
|
||||
<p>You may remember polynomials from high school, where they're those sums that look like:</p>
|
||||
\]<p>きました。<i>x</i>/<i>y</i>座標です。謎の値<i>t</i>を通して繫がっています。</p>
|
||||
<p>というわけで、普通の関数では<i>y</i>座標を<i>x</i>座標によって定義しますが、パラメトリック曲線ではそうではなく、座標の値を「制御」変数と結びつけます。<i>t</i>の値を変化させるたびに<strong>2つ</strong>の値が変化するので、これをグラフ上の座標 (<i>x</i>,<i>y</i>)として使うことができます。例えば、先ほどの関数の組は円周上の点を生成します。負の無限大から正の無限大へと<i>t</i>を動かすと、得られる座標(<i>x</i>,<i>y</i>)は常に中心(0,0)・半径1の円の上に乗ります。<i>t</i>を0から5まで変化させてプロットした場合は、このようになります(上下キーでプロットの上限を変更できます)。</p>
|
||||
<Graphic preset="empty" title="(部分)円 x=sin(t), y=cos(t)" static={true} setup={handler.setup} draw={handler.draw} onKeyDown={handler.props.onKeyDown}/>
|
||||
<p>ベジエ曲線はパラメトリック関数の一種であり、どの次元に対しても同じ基底関数を使うという点で特徴づけられます。先ほどの例では、<i>x</i>の値と<i>y</i>の値とで異なる関数(正弦関数と余弦関数)を使っていましたが、ベジエ曲線では<i>x</i>と<i>y</i>の両方で「二項係数多項式」を使います。では、二項係数多項式とは何でしょう?</p>
|
||||
<p>高校で習った、こんな形の多項式を思い出すかもしれません。</p>
|
||||
\[
|
||||
f(x) = a \cdot x^3 + b \cdot x^2 + c \cdot x + d
|
||||
\]<p>If they have a highest order term <i>x³</i> they're called "cubic" polynomials, if it's <i>x²</i> it's a "square" polynomial, if it's just <i>x</i> it's a line (and if there aren't even any terms with <i>x</i> it's not a polynomial!)</p>
|
||||
<p>Bézier curves are polynomials of <i>t</i>, rather than <i>x</i>, with the value for <i>t</i> fixed being between 0 and 1, with coefficients <i>a</i>, <i>b</i> etc. taking the "binomial" form, which sounds fancy but is actually a pretty simple description for mixing values:</p>
|
||||
\]<p>最高次の項が<i>x³</i>であれば3次多項式、<i>x²</i>であれば2次多項式と呼び、<i>x</i>だけの場合は1次多項式――ただの直線です。(そして<i>x</i>の入った項が何もなければ、多項式ではありません!)</p>
|
||||
<p>ベジエ曲線は<i>x</i>の多項式ではなく、<i>t</i>の多項式です。<i>t</i>の値は0から1までの間に制限され、その係数<i>a</i>、<i>b</i>などは「二項係数」の形をとります。というと複雑そうに聞こえますが、実際には値を組み合わせて、とてもシンプルに記述できます。</p>
|
||||
\[
|
||||
\begin{align*}
|
||||
linear &= (1-t) + t \\
|
||||
square &= (1-t)^2 + 2 \cdot (1-t) \cdot t + t^2 \\
|
||||
cubic &= (1-t)^3 + 3 \cdot (1-t)^2 \cdot t + 3 \cdot (1-t) \cdot t^2 + t^3
|
||||
\end{align*}
|
||||
\]<p>I know what you're thinking: that doesn't look too simple, but if we remove <i>t</i> and add in "times one", things suddenly look pretty easy. Check out these binomial terms:</p>
|
||||
\]<p>「そこまでシンプルには見えないよ」と思っていることでしょう。しかし仮に、<i>t</i>を取り去って係数に1を掛けることにしてしまえば、急激に簡単になります。これが二項係数部分の項です。</p>
|
||||
\[
|
||||
\begin{align*}
|
||||
linear &= \hskip{2.5em} 1 + 1 \\
|
||||
@ -119,33 +120,33 @@ Given \left (
|
||||
cubic &= \hskip{0.85em} 1 + 3 + 3 + 1\\
|
||||
hypercubic &= 1 + 4 + 6 + 4 + 1
|
||||
\end{align*}
|
||||
\]<p>Notice that 2 is the same as 1+1, and 3 is 2+1 and 1+2, and 6 is 3+3... As you can see, each time we go up a dimension, we simply start and end with 1, and everything in between is just "the two numbers above it, added together". Now <i>that's</i> easy to remember.</p>
|
||||
<p>There's an equally simple way to figure out how the polynomial terms work: if we rename <i>(1-t)</i> to <i>a</i> and <i>t</i> to <i>b</i>, and remove the weights for a moment, we get this:</p>
|
||||
\]<p>2は1+1に等しく、3は2+1や1+2に等しく、6は3+3に等しく、……ということに注目してください。見てわかるように、先頭と末尾は単に1になっていますが、中間はどれも次数が増えるたびに「上の2つの数を足し合わせた」ものになっています。<i>これなら</i>覚えやいですね。</p>
|
||||
<p>多項式部分の項がどうなっているのか、同じぐらい簡単な方法で考えることができます。仮に、<i>(1-t)</i>を<i>a</i>に、<i>t</i>を<i>b</i>に書き換え、さらに重みを一旦削除してしまえば、このようになります。</p>
|
||||
\[
|
||||
\begin{align*}
|
||||
linear &= BLUE[a] + RED[b] \\
|
||||
square &= BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot RED[b] + RED[b] \cdot RED[b] \\
|
||||
cubic &= 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{align*}
|
||||
\]<p>It's basically just a sum of "every combination of <i>a</i> and <i>b</i>", progressively replacing <i>a</i>'s with <i>b</i>'s after every + sign. So that's actually pretty simple too. So now you know binomial polynomials, and just for completeness I'm going to show you the generic function for this:</p>
|
||||
\]<p>これは要するに、「<i>a</i>と<i>b</i>のすべての組み合わせ」の単なる和です。プラスが出てくるたびに、<i>a</i>を<i>b</i>へと1つずつ置き換えていけばよいのです。こちらも本当に単純です。さて、これで「二項係数多項式」がわかりました。完璧を期するため、この関数の一般の形を示しておきます。</p>
|
||||
\[
|
||||
Bézier(n,t) = \sum_{i=0}^{n}
|
||||
\underset{binomial\ term}{\underbrace{\binom{n}{i}}}
|
||||
\cdot\
|
||||
\underset{polynomial\ term}{\underbrace{(1-t)^{n-i} \cdot t^{i}}}
|
||||
\]<p>And that's the full description for Bézier curves. Σ in this function indicates that this is a series of additions (using the variable listed below the Σ, starting at ...=<value> and ending at the value listed on top of the Σ).</p>
|
||||
\]<p>そして、これがベジエ曲線の完全な表現です。この関数中のΣは、加算の繰り返し(Σの下にある変数を使って、...=<値>から始めてΣの下にある値まで)を表します。</p>
|
||||
|
||||
<div className="howtocode">
|
||||
<h3 id="how-to-implement-the-basis-function">How to implement the basis function</h3>
|
||||
<p>We could naively implement the basis function as a mathematical construct, using the function as our guide, like this:</p>
|
||||
<h3 id="-">基底関数の実装方法</h3>
|
||||
<p>上で説明した関数を使えば、数学的な組み立て方で、基底関数をナイーブに実装することもできます。</p>
|
||||
<pre>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
|
||||
</pre>
|
||||
<p>I say we could, because we're not going to: the factorial function is <em>incredibly</em> expensive. And, as we can see from the above explanation, we can actually create Pascal's triangle quite easily without it: just start at [1], then [1,1], then [1,2,1], then [1,3,3,1], and so on, with each next row fitting 1 more number than the previous row, starting and ending with "1", with all the numbers in between being the sum of the previous row's elements on either side "above" the one we're computing.</p>
|
||||
<p>We can generate this as a list of lists lightning fast, and then never have to compute the binomial terms because we have a lookup table:</p>
|
||||
<p>「こともできる」と書いたのは、この方法では実装しない方が良いからです。階乗は<em>とてつもなく</em>重い計算なのです。また、先ほどの説明からわかるように、実際は階乗を使わなくても、かなり簡単にパスカルの三角形を作ることができます。[1]から始めて[1,1]、[1,2,1]、[1,3,3,1]、……としていくだけです。下の段は上の段よりも1つ要素が増え、各段の先頭と末尾は1になります。中間の数はどれも、左右斜め上にある両要素の和になります。</p>
|
||||
<p>このパスカルの三角形は、「リストのリスト」として瞬時に生成できます。そして、これをルックアップテーブルとして利用すれば、二項係数を計算する必要はまったくなくなります。</p>
|
||||
<pre>lut = [ [1], // n=0
|
||||
[1,1], // n=1
|
||||
[1,2,1], // n=2
|
||||
@ -165,14 +166,14 @@ binomial(n,k):
|
||||
lut.add(nextRow)
|
||||
return lut[n][k]
|
||||
</pre>
|
||||
<p>So what's going on here? First, we declare a lookup table with a size that's reasonably large enough to accommodate most lookups. Then, we declare a function to get us the values we need, and we make sure that if an n/k pair is requested that isn't in the LUT yet, we expand it first. Our basis function now looks like this:</p>
|
||||
<p>これはどのように動くのでしょう?最初に、十分に大きなサイズのルックアップテーブルを宣言します。次に、求めたい値を得るための関数を定義します。この関数は、求めたい値のn/kのペアがテーブル中にまだ存在しない場合、先にテーブルを拡張するようになっています。さて、これで基底関数は次のようになりました。</p>
|
||||
<pre>function Bezier(n,t):
|
||||
sum = 0
|
||||
for(k=0; k<=n; k++):
|
||||
sum += binomial(n,k) * (1-t)^(n-k) * t^(k)
|
||||
return sum
|
||||
</pre>
|
||||
<p>Perfect. Of course, we can optimize further. For most computer graphics purposes, we don't need arbitrary curves. We need quadratic and cubic curves (this primer actually does do arbitrary curves, so you'll find code similar to shown here), which means we can drastically simplify the code:</p>
|
||||
<p>完璧です。もちろん、さらなる最適化を施すこともできます。コンピュータグラフィクス用途ではたいてい、任意の次数の曲線が必要になるわけではありません。2次と3次の曲線だけが必要であれば、以下のようにコードを劇的に単純化することができます(実際、この入門では任意の次数までは扱いませんので、これに似たようなコードが出てきます)。</p>
|
||||
<pre>function Bezier(2,t):
|
||||
t2 = t * t
|
||||
mt = 1-t
|
||||
@ -187,9 +188,9 @@ function Bezier(3,t):
|
||||
mt3 = mt2 * mt
|
||||
return mt3 + 3*mt2*t + 3*mt*t2 + t3
|
||||
</pre>
|
||||
<p>And now we know how to program the basis function. Exellent.</p>
|
||||
<p>これで基底関数をプログラムする方法がわかりました。すばらしい。</p>
|
||||
</div>
|
||||
<p>So, now we know what the base function(s) look(s) like, time to add in the magic that makes Bézier curves so special: control points.</p>
|
||||
<p>というわけで、基底関数がどのようなものか理解できました。今度はベジエ曲線を特別にする魔法――制御点を導入する時間です。</p>
|
||||
</section>; }
|
||||
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user