1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-31 12:01:54 +02:00

Automated build

This commit is contained in:
Bezierinfo CI
2024-06-19 22:16:54 +00:00
parent d318040413
commit a638126b41
10 changed files with 272 additions and 440 deletions

686
docs/zh-CN/index.html generated
View File

@@ -35,7 +35,7 @@
<meta property="og:locale" content="zh-CN" />
<meta property="og:type" content="article" />
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
<meta property="og:updated_time" content="2024-06-19T22:12:56+00:00" />
<meta property="og:updated_time" content="2024-06-19T22:16:27+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" />
@@ -1913,8 +1913,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ · │ P │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/68dc5729d950ae8b19343df4bf9db6ec.svg"
width="269px"
src="./images/chapters/matrixsplit/1bae50fefa43210b3a6259d1984f6cbc.svg"
width="263px"
height="55px"
loading="lazy"
/>
@@ -1932,9 +1932,9 @@ B(t) = ┌ 2 3 ┐ · │ -3 3 0 0 │ · │ 2 │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/41771b04ff6a3dd2cb9532c1abb96b66.svg"
width="329px"
height="75px"
src="./images/chapters/matrixsplit/f690ff0502d9fd7d4697cc43d98afd5d.svg"
width="323px"
height="73px"
loading="lazy"
/>
<p>
@@ -1952,8 +1952,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ · │ P │ = ┌
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/b40a928e34c6ebefb6d41d8ad6e6dde9.svg"
width="667px"
src="./images/chapters/matrixsplit/f565e66677138927335535d009409c3d.svg"
width="648px"
height="55px"
loading="lazy"
/>
@@ -1971,9 +1971,9 @@ B(t) = ┌ 2 3 ┐ · │ -3 3 0 0 │ · │ 2
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/d95cc044a282d8bae130e767a69b6e68.svg"
width="809px"
height="73px"
src="./images/chapters/matrixsplit/ebf8d72c6056476172deeb89726b75c8.svg"
width="805px"
height="75px"
loading="lazy"
/>
<p>
@@ -1995,59 +1995,20 @@ B(t) = ┌ 2 ┐ · │ 0 z 0 │ · │ -2 2 0 │ · │ P │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/5333e73efdac309bfbf4e39538a66faf.svg"
width="360px"
height="55px"
loading="lazy"
/>
<!--
┌ P ┐
│ 1 │
= ┌ 2 ┐ · \underbrace\kern 2.25em Z · M \kern 2.25em · │ P │
└ 1 t t ┘ 将这一项…… │ 2 │
│ P │
└ 3 ┘
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/d121ff468b0cdfb08195970a7c8040e9.svg"
width="248px"
height="55px"
loading="lazy"
/>
<!--
┌ P ┐
-1 │ 1 │
= ┌ 2 ┐ · \underbrace M · M · Z · M · │ P │
└ 1 t t ┘ 变为这一项后…… │ 2 │
│ P │
└ 3 ┘
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/0e679db8322dc1f458c19678a46624f5.svg"
width="249px"
height="55px"
loading="lazy"
/>
<!--
┌ P ┐
│ 1 │
= ┌ 2 ┐ · M \underbrace \kern 1.25em · \kern 1.25em Q \kern 1.25em · \kern 1.25em │ P │
└ 1 t t ┘ ……得到这一项! │ 2 │
│ P │
└ 3 ┘
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/a70fc8eed71a1a96dac44d8d6dcf0f66.svg"
width="257px"
src="./images/chapters/matrixsplit/c32007be095224e0d157a8f71c62c90e.svg"
width="348px"
height="55px"
loading="lazy"
/>
<script>
console.error("LaTeX for 795cc61b6e307b6726d4f919936df57c failed.");
</script>
<script>
console.error("LaTeX for 5cc651771ad539475ac1ae5e1ce6fb0e failed.");
</script>
<script>
console.error("LaTeX for 579c0cf6bdd02de08cf30941b09a0c53 failed.");
</script>
<p>
以上变形可行是因为[<em>M</em> · <em>M</em
><sup>-1</sup
@@ -2069,9 +2030,9 @@ Q = M · Z · M = │ 1 ─ 0 │ · │ 0 z 0 │ · │ -2 2 0 │ =
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/2019b3c8df11fcbc686e05f0be22c800.svg"
width="649px"
height="55px"
src="./images/chapters/matrixsplit/5e008143622c66bb5e9cc4d5d6a8ea62.svg"
width="627px"
height="56px"
loading="lazy"
/>
<p>很好!现在得出新的二次曲线:</p>
@@ -2086,8 +2047,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/588d882a29d43956da023a0250dd7233.svg"
width="431px"
src="./images/chapters/matrixsplit/dceed84990aaf6878bcc67ddbaa8d8d9.svg"
width="417px"
height="55px"
loading="lazy"
/>
@@ -2102,8 +2063,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/945310125de20eb26b81752633e61b83.svg"
width="496px"
src="./images/chapters/matrixsplit/f63067c2c3042c374a58dfa7f692309e.svg"
width="479px"
height="55px"
loading="lazy"
/>
@@ -2119,8 +2080,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/baf6bba0cc1815cac9820f4ac437231a.svg"
width="499px"
src="./images/chapters/matrixsplit/e58196b82b78f584779208cce88137f5.svg"
width="492px"
height="55px"
loading="lazy"
/>
@@ -2147,8 +2108,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ · │ P │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/1aea275759b0b02b3bb1c038b75c0a8b.svg"
width="388px"
src="./images/chapters/matrixsplit/6a22184e6ca869d28f4a252b64f23eff.svg"
width="381px"
height="55px"
loading="lazy"
/>
@@ -2163,8 +2124,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ · │ P │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/8d4504d0a518898056d9bf7fd9ac2aa8.svg"
width="324px"
src="./images/chapters/matrixsplit/3b5e41808b6c3bc66f3da2f40651410e.svg"
width="313px"
height="55px"
loading="lazy"
/>
@@ -2180,8 +2141,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ ·
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/3a09363f9be918af61c128cde7bb238b.svg"
width="468px"
src="./images/chapters/matrixsplit/e079f44b56e07c8d7f83c17c8ebf1ecf.svg"
width="461px"
height="55px"
loading="lazy"
/>
@@ -2196,8 +2157,8 @@ B(t) = ┌ 2 ┐ · │ -2 2 0 │ ·
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/c0d460cb2be55bba1165a92f44a41990.svg"
width="423px"
src="./images/chapters/matrixsplit/4764868f43815e471bb1ea95a81e1633.svg"
width="412px"
height="57px"
loading="lazy"
/>
@@ -2212,8 +2173,8 @@ Q' = M · Z' · M = │ 1 ─ 0 │ · │ 0 1-z 2 · z · (1-z) │ ·
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/c96b720a7e0cdaaab7dc14afb480a2f5.svg"
width="755px"
src="./images/chapters/matrixsplit/c341532f693c2c1adfd298597bbfb5b5.svg"
width="729px"
height="57px"
loading="lazy"
/>
@@ -2229,8 +2190,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/0eaf7d027467b18bda51588acbe4c55e.svg"
width="436px"
src="./images/chapters/matrixsplit/e2622175dadafecc015f15c79ddf3002.svg"
width="421px"
height="55px"
loading="lazy"
/>
@@ -2245,8 +2206,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/7680eb0a64f614a0761e142b377120b6.svg"
width="491px"
src="./images/chapters/matrixsplit/4ce218bc968cbd98da0ca6ab66d415ed.svg"
width="473px"
height="57px"
loading="lazy"
/>
@@ -2262,8 +2223,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/3c8971b2b959f32e1f28e8f87251b370.svg"
width="499px"
src="./images/chapters/matrixsplit/9a4899b69e03cd4ad02c5eedffaa6a2f.svg"
width="492px"
height="57px"
loading="lazy"
/>
@@ -2289,8 +2250,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/d3385e39a74e8bd0f8884a7cc05bf131.svg"
width="587px"
src="./images/chapters/matrixsplit/480ebd0234e2fe1adc94926e8ed4339c.svg"
width="576px"
height="55px"
loading="lazy"
/>
@@ -2307,8 +2268,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/fbc0f9eb21c72bd20d19b81d6e5e8c7c.svg"
width="581px"
src="./images/chapters/matrixsplit/17e308aa6d459b1d06d3160cc8e2e786.svg"
width="571px"
height="57px"
loading="lazy"
/>
@@ -2328,8 +2289,8 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/8fbf1fa4994c2c836364a41899c2bace.svg"
width="855px"
src="./images/chapters/matrixsplit/11505e0215ef026f2e49383ebb4a1abb.svg"
width="841px"
height="75px"
loading="lazy"
/>
@@ -2349,9 +2310,9 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
-->
<img
class="LaTeX SVG"
src="./images/chapters/matrixsplit/a40d603c43ecca7ea62ee588acef6385.svg"
width="849px"
height="76px"
src="./images/chapters/matrixsplit/a899891096d82b7fdb23a90e6106b6df.svg"
width="837px"
height="77px"
loading="lazy"
/>
<p>
@@ -2373,16 +2334,9 @@ B(t) = ┌ 2 ┐ · M · Q · │ P │ = ┌ 2 ┐ · M · │
如果有一条二次曲线那么可以如下构造三次曲线精确重现原来的曲线首先选择相同的起点和终点然后两个控制点分别选为“1/3<em>起点+2/3</em>终点”和“2/3<em>起点+1/3</em>终点”。所得曲线与原来的相同,只不过表示为了三次曲线而不是二次曲线。
</p>
<p><em>n</em>次曲线升为<em>n+1</em>次曲线的一般规则如下(注意起点和终点的权重与旧曲线的相同):</p>
<!--
╭ (k-i) · w + i · w ╮
__ k i k-i i │ i i-1 │
Bézier(k,t) = \underbrace\mathrmC · \ \underbrace(1-t) · t \ · \ \underbrace│ ─────────────────────── │ ,其中\ k=n+1
‾‾ i=0 k 二项式系数项 多项式项 ╰ k ╯ 新权重
w =0
-1
-->
<img class="LaTeX SVG" src="./images/chapters/reordering/649574c4876d3a61a8060265c2f8b985.svg" width="680px" height="61px" loading="lazy" />
<script>
console.error("LaTeX for 741076c39df999c680a563b207fe30e5 failed.");
</script>
<p>
然而这一规则也直接意味着通常<strong>无法</strong><em>n</em>次曲线稳妥地降到<em>n-1</em>次,这是因为控制点无法被简洁地“拆开”。可以做些尝试,但所得曲线不会与原曲线重合,而且其实还可能看起来完全不同。
</p>
@@ -2393,13 +2347,9 @@ Bézier(k,t) = \underbrace\mathrmC · \ \underbrace(1-t)
>中亦有解释),但是为了用上这种方法,需要先做些变形再转用线性代数。正如矩阵表示一章所言,有些东西用矩阵去做比用函数方便得多,而这就是一例。那么……开始吧!
</p>
<p>先将标准的贝塞尔函数写得紧凑一些:</p>
<!--
__ n n n i n-i i
Bézier(n,t) = w B (t) ,其中\ B (t) = \mathrmC · (1-t) · t
‾‾ i=0 i i i n
-->
<img class="LaTeX SVG" src="./images/chapters/reordering/ec952f600305895ccf637fc428b31dfd.svg" width="413px" height="41px" loading="lazy" />
<script>
console.error("LaTeX for f871a8897751f1eec570b6dccb4c7fc0 failed.");
</script>
<p>
然后用一个朴素(其实极其有用)的变形技巧:既然<code>t</code>值总在0到1之间含端点<code>1-t</code><code>t</code>恒等于1那么任何数都可表示为<code>t</code><code>1-t</code>的和:
</p>
@@ -2407,7 +2357,7 @@ Bézier(n,t) = w B (t) ,其中\ B (t) = \mathrmC · (1-t) ·
x = 1 x = ((1-t) + t) x = (1-t) x + t x = x (1-t) + x t
-->
<img class="LaTeX SVG" src="./images/chapters/reordering/ea6c8636e76ce935064fc85c692e7b4d.svg" width="384px" height="17px" loading="lazy" />
<img class="LaTeX SVG" src="./images/chapters/reordering/ff224ded6bbbc94b43130f5f8eeb5d29.svg" width="379px" height="16px" loading="lazy" />
<p>于是用这一看似平凡的性质可将贝塞尔函数拆分为<code>1-t</code><code>t</code>两部分之和:</p>
<!--
@@ -2416,90 +2366,30 @@ Bézier(n,t)= (1-t) B(n,t) + t B(n,t)
= w (1 - t) B (t) + w t B (t)
‾‾ i=0 i i ‾‾ i=0 i i
-->
<img class="LaTeX SVG" src="./images/chapters/reordering/fcfc5f7e3341a7494341d5cd42d9b60d.svg" width="332px" height="68px" loading="lazy" />
<img class="LaTeX SVG" src="./images/chapters/reordering/0cf0d5f856ec204dc32e0e42691cc70a.svg" width="316px" height="67px" loading="lazy" />
<p>目前一切顺利。现在为了理解为什么这么做,将<code>1-t</code><code>t</code>两部分具体写出并观察结果。首先是<code>1-t</code></p>
<!--
n n! n-i i
(1 - t) B (t)= (1-t) ──────── (1-t) t
i (n-i)!i!
n+1-i (n+1)! n+1-i i
= ───── ────────── (1-t) t
n+1 (n+1-i)!i!
k-i k! k-i i
= ─── ──────── (1-t) t ,其中\ k = n + 1
k (k-i)!i!
k-i k
= ─── B (t)
k i
-->
<img
class="LaTeX SVG"
src="./images/chapters/reordering/4d7f29b041d912df5ca99ff23cb77a70.svg"
width="403px"
height="163px"
loading="lazy"
/>
<script>
console.error("LaTeX for 4df474f0dcfc7a7cb49d1fd154a86212 failed.");
</script>
<p>
用这一看似朴素的技巧瞬间就将n次贝塞尔函数的一个部分用n+1次贝塞尔函数表示出来了这非常像曲线升次当然<code>t</code>的部分也要表示出来,但这不是问题:
</p>
<!--
n n! n-i i
t B (t)= t ──────── (1-t) t
i (n-i)!i!
i+1 (n+1)! (n+1)-(i+1) i+1
= ─── ──────────────────── (1-t) t
n+1 ((n+1)-(i+1))!(i+1)!
i+1 k! k-(i+1) i+1
= ─── ──────────────── (1-t) t ,其中\ k = n + 1
k (k-(i+1))!(i+1)!
i+1 k
= ─── B (t)
k i+1
-->
<img
class="LaTeX SVG"
src="./images/chapters/reordering/d3b88143515b7f137c42e816d4cbdc2d.svg"
width="481px"
height="161px"
loading="lazy"
/>
<script>
console.error("LaTeX for 3454e67c644ffcb21aa6a4d00e399299 failed.");
</script>
<p>
<code>n</code>次的表达式变为<code>n+1</code>次的之后再将其重新合并。虽然<code>n</code>次函数是从0到<code>n</code>求和,<code>n+1</code>次函数是从0到<code>n+1</code>求和,但补上“贡献为零”的项即可。下一章“导数”会论述为什么“没有对应的二项式系数的更高次项”和“低于零次的项”都“贡献为零”,因此需要什么形式的项就可以加上什么项。将这些项包含在和式中没有影响,而所得函数与低次曲线依然相等:
</p>
<!--
__ n+1 n __ n+1 n
Bézier(n,t)= w (1 - t) B (t) + w t B (t)
‾‾ i=0 i i ‾‾ i=0 i i
__ n+1 k-i k __ n+1 i+1 k
= w ─── B (t) + w ─── B (t) ,其中\ k = n + 1
‾‾ i=0 i k i ‾‾ i=0 i k i+1
__ n+1 k-i k __ n+1 i k
= w ─── B (t) + p ─ B (t)
‾‾ i=0 i k i ‾‾ i=0 i-1 k i
__ n+1 ╭ k-i i ╮ k
= │ w ─── + p ─ │ B (t)
‾‾ i=0 ╰ i k i-1 k ╯ i
__ n+1 k i
= (w (1-s) + p s) B (t) ,其中\ s = ─
‾‾ i=0 i i-1 i k
-->
<img
class="LaTeX SVG"
src="./images/chapters/reordering/a81ac8ec82d7fbe2ce094b2a90d24769.svg"
width="483px"
height="257px"
loading="lazy"
/>
<script>
console.error("LaTeX for 1b87d75ee33866bcc46defde62c7f415 failed.");
</script>
<p>接下来从变形转到线性代数矩阵——现在Bézier(n,t)和Bézier(n+1,t)之间的关系可用非常简单的矩阵乘法表示:</p>
<!--
M B = B
n k
-->
<img class="LaTeX SVG" src="./images/chapters/reordering/d71f7c4a43620dd15be7816e2a335b24.svg" width="77px" height="17px" loading="lazy" />
<img class="LaTeX SVG" src="./images/chapters/reordering/1f5b60d190a1c7099b3411e4cc477291.svg" width="71px" height="16px" loading="lazy" />
<p>其中矩阵<strong>M</strong><code>(n+1)×n</code>阶的矩阵,其形如:</p>
<!--
@@ -2525,9 +2415,9 @@ M = │ k k │
-->
<img
class="LaTeX SVG"
src="./images/chapters/reordering/cc293416bf824d94dd12aca70281d8f7.svg"
width="340px"
height="172px"
src="./images/chapters/reordering/056e25c397c524d80f378ce3823c7e78.svg"
width="336px"
height="187px"
loading="lazy"
/>
<p>
@@ -2560,9 +2450,9 @@ M = │ k k │
-->
<img
class="LaTeX SVG"
src="./images/chapters/reordering/c49f71f865f3cccfa35fa335142a0837.svg"
width="288px"
height="109px"
src="./images/chapters/reordering/46e64dc07502e14217ec83d755f736ee.svg"
width="272px"
height="116px"
loading="lazy"
/>
<p>其中的步骤为:</p>
@@ -2617,8 +2507,8 @@ Bézier'(n,t) = n · (b -b ) · Bézier(n-1,t)
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/9a0f17ecc520e05ad571d02a196182af.svg"
width="341px"
src="./images/chapters/derivatives/a7b79877822a8f60e45552dcafc0815d.svg"
width="333px"
height="44px"
loading="lazy"
/>
@@ -2631,8 +2521,8 @@ Bézier'(n,t) = Bézier(n-1,t) · n · (w -w )
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/c1e13183f8bb938665e401fc3cebfe31.svg"
width="352px"
src="./images/chapters/derivatives/8f78fdb9ef54b1bc4dbc00f07263cc97.svg"
width="343px"
height="44px"
loading="lazy"
/>
@@ -2649,134 +2539,39 @@ Bézier'(n,t) = Bézier(n-1,t) · n · (w -w )
<p>
虽然有时候有人告诉说“这是导数”就行,但还是可能想一探究竟。既然如此,就来看看这个导数的证明。首先,因为权重不影响完整的贝塞尔函数的求导,所以求导只涉及多项式基函数的导数。基函数的导数为:
</p>
<!--
\mathrmd \mathrmd ╭ k k n-k ╮
───────── B (t) = ───────── │ \mathrmC t (1-t) │
\mathrmdt n,k \mathrmdt ╰ n ╯
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/d3d2c3d668be7a43b9ec08a639c8657c.svg"
width="223px"
height="35px"
loading="lazy"
/>
<script>
console.error("LaTeX for 0f4989a2f49b11a73bdfd9ef9cb57568 failed.");
</script>
<p>
使用<a href="https://en.wikipedia.org/wiki/Product_rule">乘积求导法则</a><a href="https://en.wikipedia.org/wiki/Chain_rule"
>复合函数求导法则</a
>得到:
</p>
<!--
k k-1 n-k k n-k-1
⋯= \mathrmC (k · t (1-t) + t · (1-t) · (n-k) · -1)
n
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/5a9ccc4f099fbdd4e64760c8e7099193.svg"
width="408px"
height="20px"
loading="lazy"
/>
<script>
console.error("LaTeX for 5ab476101798830208dc72f01b21534f failed.");
</script>
<p>上式不易处理,因此打开括号:</p>
<!--
kn! k-1 n-k (n-k)n! k n-1-k
⋯= ──────── t (1-t) - ──────── t (1-t)
k!(n-k)! k!(n-k)!
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/ca58832a6776fe2722597b96bc53afe0.svg"
width="389px"
height="39px"
loading="lazy"
/>
<script>
console.error("LaTeX for da41db4de14b211d26d6e267f98c1205 failed.");
</script>
<p>
现在技巧性的一步是将上式再次化为含二项式系数的形式需要得到形如“x!/y!(x-y)!”的项。如果得到关于<em>n</em>-1和<em>k</em>-1的项那么说明方向是对的。
</p>
<!--
n! k-1 n-k (n-k)n! k n-1-k
⋯= ──────────── t (1-t) - ──────── t (1-t)
(k-1)!(n-k)! k!(n-k)!
╭ (n-1)! k-1 n-k (n-k)(n-1)! k n-1-k ╮
⋯= n │ ──────────── t (1-t) - ─────────── t (1-t) │
╰ (k-1)!(n-k)! k!(n-k)! ╯
╭ (n-1)! k-1 (n-1)-(k-1) (n-1)! k (n-1)-k ╮
⋯= n │ ──────────────────── t (1-t) - ──────────── t (1-t) │
╰ (k-1)!((n-1)-(k-1))! k!((n-1)-k)! ╯
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/3de9c86a05a3b828b878af7f87b1d0cd.svg"
width="524px"
height="73px"
loading="lazy"
/>
<script>
console.error("LaTeX for eb4f41449b27eabcbede86e7e93fadc5 failed.");
</script>
<p>这是第一步。上式括号里的两项其实为标准的、低一次的贝塞尔函数:</p>
<!--
╭ x! y x-y x! k x-k ╮
⋯= n │ ──────── t (1-t) - ──────── t (1-t) │ ,其中\ x=n-1 y=k-1
╰ y!(x-y)! k!(x-k)! ╯
⋯= n (B (t) - B (t))
n-1,k-1 n-1,k
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/7d40ba12784e40c8dd9bc1ddbc407519.svg"
width="547px"
height="45px"
loading="lazy"
/>
<script>
console.error("LaTeX for 5918196b12b0ebd26f4194ad9f1afe7e failed.");
</script>
<p>现在将上式应用于已有的加权贝塞尔函数。先写出之前所见的平面曲线公式,再逐步求出导数:</p>
<!--
Bézier (t) = B (t) · w + B (t) · w + B (t) · w + B (t) · w + ⋯
n,k n,0 0 n,1 1 n,2 2 n,3 3
\mathrmd
───────── Bézier (t) = n · (B (t) - B (t)) · w +
\mathrmdt n,k n-1,-1 n-1,0 0
n · (B (t) - B (t)) · w +
n-1,0 n-1,1 1
n · (B (t) - B (t)) · w +
n-1,1 n-1,2 2
n · (B (t) - B (t)) · w +
n-1,2 n-1,3 3
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/981f7eb4406d8952e6fe5076fa687b63.svg"
width="539px"
height="109px"
loading="lazy"
/>
<script>
console.error("LaTeX for 6b673b53e775ca4c0673bd1700dac915 failed.");
</script>
<p>如果打开上式的括号(用颜色表示相匹配的项),再按递增的<em>k</em>值重排各项,那么有:</p>
<!--
n · B (t) · w +
n-1,-1 0
n · B (t) · w - n · B (t) · w +
n-1,\colorblue 0 1 n-1,\colorblue 0 0
n · B (t) · w - n · B (t) · w +
n-1,\colorred 1 2 n-1,\colorred 1 1
n · B (t) · w - n · B (t) · w +
n-1,\colormagenta 2 3 n-1,\colormagenta 2 2
- n · B (t) · w +
n-1,3 3
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/a10dfaa20f01a2169e97046c2611614f.svg"
width="304px"
height="108px"
loading="lazy"
/>
<script>
console.error("LaTeX for d6f9752688adc63d2e8e59bd4a8f1052 failed.");
</script>
<p>
上式中有两项会消失掉:因为任意和式都没有第-1项所以上式第一项消失。既然这一项总是贡献为零那么求导时就可以放心地将其完全无视。消失的另外一项为展开式的最后一项——包含<em
>B</em
@@ -2784,98 +2579,32 @@ n · B (t) · w - n · B (t) · w +
>的一项。这一项含有二项式系数C<sub><em>i</em></sub
><sup><em>i</em>+1</sup>而这一系数通常约定等于0。因此这一项贡献为零也可被略去。这意味着剩下的项为
</p>
<!--
n · B (t) · w - n · B (t) · w +
n-1,\colorblue 0 1 n-1,\colorblue 0 0
n · B (t) · w - n · B (t) · w +
n-1,\colorred 1 2 n-1,\colorred 1 1
n · B (t) · w - n · B (t) · w +
n-1,\colormagenta 2 3 n-1,\colormagenta 2 2
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/7e29caedfb6b82f06c2ba70fafa0a3cd.svg"
width="295px"
height="69px"
loading="lazy"
/>
<script>
console.error("LaTeX for 09a3dcf9aa4456533cb247a95b64874c failed.");
</script>
<p>此即低次函数之和:</p>
<!--
\mathrmd
───────── Bézier (t) = n · B (t) · (w - w ) + n · B (t) · (w - w ) + n · B (t) · (w - w )
\mathrmdt n,k n-1,\colorblue 0 1 0 n-1,\colorred 1 2 1 n-1,\colormagenta 2 3 2
+ ⋯
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/92683b35a94f50bc390a0f5281f3fdec.svg"
width="685px"
height="35px"
loading="lazy"
/>
<script>
console.error("LaTeX for 030b8158d79256ba3967b59be4b8d3be failed.");
</script>
<p>将上式改写为正常的和式即可:</p>
<!--
\mathrmd __ n-1 __ n-1
───────── Bézier (t) = n · B (t) · (w - w ) = B (t) · \underbracen · (w - w )
\mathrmdt n,k ‾‾ k=0 n-1,k k+1 k ‾‾ k=0 n-1,k k+1 k 导数的权重
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/557dbd54f60ba895e1b5bb3efa2715e3.svg"
width="555px"
height="52px"
loading="lazy"
/>
<script>
console.error("LaTeX for 8a3e5634f1fe66ebb25f25dc52925fc8 failed.");
</script>
</div>
<p>将上式改写为与原式相似的形式有助于看出它们的区别。先写出原式,再写出导数:</p>
<!--
__ n i n-i i
Bézier(n,t) = \underbrace\mathrmC · \ \underbrace(1-t) · t · \ \underbracew
‾‾ i=0 n 二项式系数项 多项式项 i 权重
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/9c90e59048b0f5db6d926acdab756506.svg"
width="333px"
height="48px"
loading="lazy"
/>
<!--
__ k i k-i i
Bézier'(n,t) = \underbrace\mathrmC · \ \underbrace(1-t) · t · \ \underbracen · (w - w ) ,其中\ k=n-1
‾‾ i=0 k 二项式系数项 多项式项 i+1 i 导数的权重
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/72933f4b71b28c560b45618f519fc5e4.svg"
width="539px"
height="52px"
loading="lazy"
/>
<script>
console.error("LaTeX for 7c228404ef3242bae827213a57d10849 failed.");
</script>
<script>
console.error("LaTeX for 8f4b950b11babf2d6d54fdf2421cf11a failed.");
</script>
<p>
有什么区别?对于实际的贝塞尔曲线而言几乎没有区别!虽然次数降低了(从<em>n</em>次变为<em>n</em>-1次但是贝塞尔函数没有改变。唯一的真正的区别在于推导表示曲线的函数时权重如何变化。如果有A、B、C、D四个点那么导数有三个点二阶导数有两个点三阶导数有一个点
</p>
<!--
B(n,t) w = {A,B,C,D}
B'(n,t) n = 3 w' = {A',B',C'} = {3 · (B-A),\ 3 · (C-B),\ 3 · (D-C)}
B''(n,t) n = 2 w'' = {A'',B''} = {2 · (B'-A'),\ 2 · (C'-B')}
B'''(n,t) n = 1 w''' = {A'''} = {1 · (B''-A'')}
-->
<img
class="LaTeX SVG"
src="./images/chapters/derivatives/5821cdc680d91ce5650e713854e5201a.svg"
width="595px"
height="76px"
loading="lazy"
/>
<script>
console.error("LaTeX for ddd559d3ad77f5801523f6b3968d9fc8 failed.");
</script>
<p>
只要有多于一个权重即可运用这一方法。只剩一个权重时,下一步会出现<em>k</em>=0而贝塞尔函数的和式因为无项可加而化为零。因此二次函数没有二阶导数三次函数没有三阶导数更一般地有<em>n</em>次函数有<em>n</em>-1阶有意义的导数其更高阶导数为零。
</p>
@@ -2900,9 +2629,9 @@ tangent (t) = B' (t)
-->
<img
class="LaTeX SVG"
src="./images/chapters/pointvectors/24fcd90641a3a352f373f4e68fe5c004.svg"
width="133px"
height="60px"
src="./images/chapters/pointvectors/da069c7d6cbdb516c5454371dae84e7f.svg"
width="132px"
height="61px"
loading="lazy"
/>
<p>此即所需的方向向量。可以在每一点将方向向量规范化后得到单位方向向量即长度为1.0),再根据这些方向进行所需的操作:</p>
@@ -2925,32 +2654,17 @@ y(t) = \| tangent (t)\| = ─────────────── = ──
-->
<img
class="LaTeX SVG"
src="./images/chapters/pointvectors/ff94b5f90ced1a388a70cae2bfbabded.svg"
width="276px"
height="120px"
src="./images/chapters/pointvectors/33afd1a141ec444989c393b3e51ec9ca.svg"
width="273px"
height="121px"
loading="lazy"
/>
<p>
切向量对于沿曲线移动很有用,但如果要从曲线附近“移向远处”,而且移动方向与曲线在某点<em>t</em>处垂直,那该怎么办?这时需要的是<em></em>向量。这一向量与曲线的方向保持垂直且长度通常为1.0,因此只需旋转单位方向向量即可:
</p>
<!--
^ \pi ^ \pi ^
normal (t) = x(t) · cos ─── - y(t) · sin ─── = - y(t)
x 2 2
^ \pi ^ \pi ^
normal (t) = \underbrace x(t) · sin ─── + y(t) · cos ─── = x(t)
y 2 2 o
90 旋转
-->
<img
class="LaTeX SVG"
src="./images/chapters/pointvectors/35683edb9348be942f78b01d8de13759.svg"
width="317px"
height="77px"
loading="lazy"
/>
<script>
console.error("LaTeX for f41e9aa27ef92e2b0127d0343ff8f42d failed.");
</script>
<div class="note">
<p>
其实旋转坐标只要知道方法就非常简单——“施加<a href="https://en.wikipedia.org/wiki/Rotation_matrix">旋转矩阵</a
@@ -2964,8 +2678,8 @@ y' = x · sin (\phi) + y · cos (\phi)
-->
<img
class="LaTeX SVG"
src="./images/chapters/pointvectors/5ad898109abeb8e035abe47325bb5fa0.svg"
width="179px"
src="./images/chapters/pointvectors/1df6c055ae8e41a46bfdebc55a4f17c0.svg"
width="183px"
height="37px"
loading="lazy"
/>
@@ -2977,8 +2691,8 @@ y' = x · sin (\phi) + y · cos (\phi)
-->
<img
class="LaTeX SVG"
src="./images/chapters/pointvectors/99a4919e874959c4506ecd3598bd498d.svg"
width="205px"
src="./images/chapters/pointvectors/f02e359a5e47667919738fff69d2625b.svg"
width="211px"
height="40px"
loading="lazy"
/>
@@ -3112,19 +2826,51 @@ y' = x · sin (\phi) + y · cos (\phi)
<div class="howtocode">
<h3>实现旋转最小化标架</h3>
<p>首先假设已有函数用于计算上文提及的指定点的弗勒内标架,输出的标架具有如下性质:</p>
<pre><code>{
<table class="code">
<tr>
<td>1</td>
<td rowspan="6">
<textarea disabled rows="6" role="doc-example">
{
o所有向量的起点即线上点
t切向量
r旋转轴向量
n法向量
}</code></pre>
}</textarea
>
</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>5</td>
</tr>
<tr>
<td>6</td>
</tr>
</table>
<p>再如下写出生成一系列旋转最小化标架的函数:</p>
<pre><code>generateRMFrames(steps) -&gt; frames:
<table class="code">
<tr>
<td>1</td>
<td rowspan="28">
<textarea disabled rows="28" role="doc-example">
generateRMFrames(steps) -> frames:
step = 1.0/steps
// 从曲线上t=0处标准的切向量/旋转轴/法向量标架开始:
frames.add(getFrenetFrame(0))
// 开始构造旋转最小化标架:
for t0 = 0, t0 &lt; 1.0, t0 += step:
for t0 = 0, t0 < 1.0, t0 += step:
// 从已有的上一标架开始
x0 = frames.last
// 求出下一标架要保留它的位置和切向量
@@ -3146,7 +2892,93 @@ y' = x · sin (\phi) + y · cos (\phi)
// 收尾工作
x1.r = riL - v2 * 2/c2 * v2 · riL
x1.n = x1.r × x1.t
frames.add(x1)</code></pre>
frames.add(x1)</textarea
>
</td>
</tr>
<tr>
<td>2</td>
</tr>
<tr>
<td>3</td>
</tr>
<tr>
<td>4</td>
</tr>
<tr>
<td>5</td>
</tr>
<tr>
<td>6</td>
</tr>
<tr>
<td>7</td>
</tr>
<tr>
<td>8</td>
</tr>
<tr>
<td>9</td>
</tr>
<tr>
<td>10</td>
</tr>
<tr>
<td>11</td>
</tr>
<tr>
<td>12</td>
</tr>
<tr>
<td>13</td>
</tr>
<tr>
<td>14</td>
</tr>
<tr>
<td>15</td>
</tr>
<tr>
<td>16</td>
</tr>
<tr>
<td>17</td>
</tr>
<tr>
<td>18</td>
</tr>
<tr>
<td>19</td>
</tr>
<tr>
<td>20</td>
</tr>
<tr>
<td>21</td>
</tr>
<tr>
<td>22</td>
</tr>
<tr>
<td>23</td>
</tr>
<tr>
<td>24</td>
</tr>
<tr>
<td>25</td>
</tr>
<tr>
<td>26</td>
</tr>
<tr>
<td>27</td>
</tr>
<tr>
<td>28</td>
</tr>
</table>
<p>即使忽略注释,代码也明显比计算单个弗勒内标架的多,但也没有多得离谱,而且得到了长得更好的法向量。</p>
</div>