1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-09-25 15:49:06 +02:00

fallback autogeneration

This commit is contained in:
Pomax
2020-08-06 09:22:54 -07:00
parent 6ab0c4faef
commit 0797083600
15 changed files with 349 additions and 322 deletions

View File

@@ -3,19 +3,8 @@
Let's start with the good stuff: when we're talking about Bézier curves, we're talking about the things that you can see in the following graphics. They run from some start point to some end point, with their curvature influenced by one or more "intermediate" control points. Now, because all the graphics on this page are interactive, go manipulate those curves a bit: click-drag the points, and see how their shape changes based on what you do. Let's start with the good stuff: when we're talking about Bézier curves, we're talking about the things that you can see in the following graphics. They run from some start point to some end point, with their curvature influenced by one or more "intermediate" control points. Now, because all the graphics on this page are interactive, go manipulate those curves a bit: click-drag the points, and see how their shape changes based on what you do.
<div class="figure"> <div class="figure">
<graphics-element title="A quadratic Bézier curve" width="275" height="275" src="./chapters/introduction/quadratic.js"> <graphics-element title="A quadratic Bézier curve" width="275" height="275" src="./chapters/introduction/quadratic.js"></graphics-element>
<fallback-image> <graphics-element title="A cubic Bézier curve" width="275" height="275" src="./chapters/introduction/cubic.js"></graphics-element>
<img src="./chapters/introduction/quadratic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
<graphics-element title="A cubic Bézier curve" width="275" height="275" src="./chapters/introduction/cubic.js">
<fallback-image>
<img src="./chapters/introduction/cubic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
</div> </div>
These curves are used a lot in computer aided design and computer aided manufacturing (CAD/CAM) applications, as well as in graphic design programs like Adobe Illustrator and Photoshop, Inkscape, GIMP, etc. and in graphic technologies like scalable vector graphics (SVG) and OpenType fonts (TTF/OTF). A lot of things use Bézier curves, so if you want to learn more about them... prepare to get your learn on! These curves are used a lot in computer aided design and computer aided manufacturing (CAD/CAM) applications, as well as in graphic design programs like Adobe Illustrator and Photoshop, Inkscape, GIMP, etc. and in graphic technologies like scalable vector graphics (SVG) and OpenType fonts (TTF/OTF). A lot of things use Bézier curves, so if you want to learn more about them... prepare to get your learn on!

View File

@@ -3,19 +3,8 @@
まずは良い例から始めましょう。ベジエ曲線というのは、下の図に表示されているもののことです。ベジエ曲線はある始点からある終点へと延びており、その曲率は1個以上の「中間」制御点に左右されています。さて、このページの図はどれもインタラクティブになっていますので、ここで曲線をちょっと操作してみましょう。点をドラッグしたとき、曲線の形がそれに応じてどう変化するのか、確かめてみてください。 まずは良い例から始めましょう。ベジエ曲線というのは、下の図に表示されているもののことです。ベジエ曲線はある始点からある終点へと延びており、その曲率は1個以上の「中間」制御点に左右されています。さて、このページの図はどれもインタラクティブになっていますので、ここで曲線をちょっと操作してみましょう。点をドラッグしたとき、曲線の形がそれに応じてどう変化するのか、確かめてみてください。
<div class="figure"> <div class="figure">
<graphics-element title="2次のベジエ曲線" width="275" height="275" src="./chapters/introduction/quadratic.js"> <graphics-element title="2次のベジエ曲線" width="275" height="275" src="./chapters/introduction/quadratic.js"></graphics-element>
<fallback-image> <graphics-element title="3次のベジエ曲線" width="275" height="275" src="./chapters/introduction/cubic.js"></graphics-element>
<img src="./chapters/introduction/quadratic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
<graphics-element title="3次のベジエ曲線" width="275" height="275" src="./chapters/introduction/cubic.js">
<fallback-image>
<img src="./chapters/introduction/cubic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
</div> </div>
ベジエ曲線は、CADcomputer aided designやCAMcomputer aided manufacturingのアプリケーションで多用されています。もちろん、Adobe Illustrator・Photoshop・Inkscape・Gimp などのグラフィックデザインアプリケーションや、SVGscalable vector graphics・OpenTypeフォントotf/ttfのようなグラフィック技術でも利用されています。ベジエ曲線はたくさんのものに使われていますので、これについてもっと詳しく学びたいのであれば……さあ、準備しましょう ベジエ曲線は、CADcomputer aided designやCAMcomputer aided manufacturingのアプリケーションで多用されています。もちろん、Adobe Illustrator・Photoshop・Inkscape・Gimp などのグラフィックデザインアプリケーションや、SVGscalable vector graphics・OpenTypeフォントotf/ttfのようなグラフィック技術でも利用されています。ベジエ曲線はたくさんのものに使われていますので、これについてもっと詳しく学びたいのであれば……さあ、準備しましょう

View File

@@ -3,19 +3,8 @@
让我们有个好的开始:当我们在谈论贝塞尔曲线的时候,所指的就是你在如下图像看到的东西。它们从某些起点开始,到终点结束,并且受到一个或多个的“中间”控制点的影响。本页面上的图形都是可交互的,你可以拖动这些点,看看这些形状在你的操作下会怎么变化。 让我们有个好的开始:当我们在谈论贝塞尔曲线的时候,所指的就是你在如下图像看到的东西。它们从某些起点开始,到终点结束,并且受到一个或多个的“中间”控制点的影响。本页面上的图形都是可交互的,你可以拖动这些点,看看这些形状在你的操作下会怎么变化。
<div class="figure"> <div class="figure">
<graphics-element title="二次贝塞尔曲线" width="275" height="275" src="./chapters/introduction/quadratic.js"> <graphics-element title="二次贝塞尔曲线" width="275" height="275" src="./chapters/introduction/quadratic.js"></graphics-element>
<fallback-image> <graphics-element title="三次贝塞尔曲线" width="275" height="275" src="./chapters/introduction/cubic.js"></graphics-element>
<img src="./chapters/introduction/quadratic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
<graphics-element title="三次贝塞尔曲线" width="275" height="275" src="./chapters/introduction/cubic.js">
<fallback-image>
<img src="./chapters/introduction/cubic.png" width="275" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
</div> </div>
这些曲线在计算机辅助设计和计算机辅助制造应用CAD/CAM中用的很多。在图形设计软件中也常用到像Adobe Illustrator, Photoshop, Inkscape, Gimp等等。还可以应用在一些图形技术中像矢量图形SVG和OpenType字体ttf/otf。许多东西都用到贝塞尔曲线如果你想更了解它们...准备好继续往下学吧! 这些曲线在计算机辅助设计和计算机辅助制造应用CAD/CAM中用的很多。在图形设计软件中也常用到像Adobe Illustrator, Photoshop, Inkscape, Gimp等等。还可以应用在一些图形技术中像矢量图形SVG和OpenType字体ttf/otf。许多东西都用到贝塞尔曲线如果你想更了解它们...准备好继续往下学吧!

View File

@@ -6,27 +6,20 @@ Bézier curves are the result of [linear interpolations](https://en.wikipedia.or
If we know the distance between those two points, and we want a new point that is, say, 20% the distance away from the first point (and thus 80% the distance away from the second point) then we can compute that really easily: If we know the distance between those two points, and we want a new point that is, say, 20% the distance away from the first point (and thus 80% the distance away from the second point) then we can compute that really easily:
<script type="text/latex"> \[
Given \left ( Given \left (
\begin{aligned}
\begin{aligned} p_1 &= some\ point \\
p_1 &= some\ point \\ p_2 &= some\ other\ point \\
p_2 &= some\ other\ point \\ distance &= (p_2 - p_1) \\
distance &= (p_2 - p_1) \\ ratio &= \frac{percentage}{100} \\
ratio &= \frac{percentage}{100} \\ \end{aligned}
\end{aligned} \right ),\ our\ new\ point = p_1 + distance \cdot ratio
\]
\right ) \text{, our new point} = p_1 + distance \cdot ratio
</script>
So let's look at that in action: the following graphic is interactive in that you can use your up and down arrow keys to increase or decrease the interpolation ratio, to see what happens. We start with three points, which gives us two lines. Linear interpolation over those lines gives us two points, between which we can again perform linear interpolation, yielding a single point. And that point —and all points we can form in this way for all ratios taken together— form our Bézier curve: So let's look at that in action: the following graphic is interactive in that you can use your up and down arrow keys to increase or decrease the interpolation ratio, to see what happens. We start with three points, which gives us two lines. Linear interpolation over those lines gives us two points, between which we can again perform linear interpolation, yielding a single point. And that point —and all points we can form in this way for all ratios taken together— form our Bézier curve:
<graphics-element title="Linear Interpolation leading to Bézier curves" width="825" height="275" src="./chapters/whatis/interpolation.js"> <graphics-element title="Linear Interpolation leading to Bézier curves" width="825" height="275" src="./chapters/whatis/interpolation.js"></graphics-element>
<fallback-image>
<img src="./chapters/whatis/interpolation.png" width="825" height="275">
{{ disableMessage }}
</fallback-image>
</graphics-element>
And that brings us to the complicated maths: calculus. And that brings us to the complicated maths: calculus.

View File

@@ -0,0 +1,28 @@
# ではベジエ曲線はどうやってできるのでしょう?
ベジエ曲線がどのように動くのか、点を触ってみて感覚が摑めたかもしれません。では、実際のところベジエ曲線*とは*いったい何でしょうかこれを説明する方法は2通りありますが、どちらの説明でも行き着く先はまったく同じです。一方は複雑な数学を使うのに対し、もう一方はとても簡単です。というわけで……簡単な説明の方から始めましょう。
ベジエ曲線は、[線形補間](https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E8%A3%9C%E9%96%93)の結果です。というと難しそうに聞こえますが、誰でも幼い頃から線形補間をやってきています。例えば、何か2つのものの間を指し示すときには、いつも線形補間を行っています。線形補間とは、単純に「2点の間から点を得る」ことなのです。
例えば、2点間の距離がわかっているとして、一方の点から距離の20%だけ離れたすなわち、もう一方の点から80%離れた)新しい点を求めたい場合、次のようにとても簡単に計算できます。
\[
\left (
\begin{aligned}
p_1 &= 一方の点 \\
p_2 &= もう一方の点 \\
距離 &= (p_2 - p_1) \\
比率 &= \frac{百分率}{100} \\
\end{aligned}
\right )のとき、新しい点 = p_1 + 距離 \cdot 比率
\]
では、実際に見てみましょう。下の図はインタラクティブになっています。上下キーで補間の比率が増減しますので、どうなるか確かめてみましょう。最初に3点があり、それを結んで2本の直線が引かれています。この直線の上でそれぞれ線形補間を行うと、2つの点が得られます。この2点の間でさらに線形補間を行うと、1つの点を得ることができます。そして、あらゆる比率に対して同様に点を求め、それをすべて集めると、このようにベジエ曲線ができるのです。
<graphics-element title="Linear Interpolation leading to Bézier curves" width="825" height="275" src="./chapters/whatis/interpolation.js"></graphics-element>
また、これが複雑な方の数学につながっていきます。微積分です。
いま上で行ったものとは似つかないように思えますが、実はあれは2次曲線を描いていたのです。ただし一発で描きあげるのではなく、手順を追って描いていきました。ベジエ曲線は多項式関数で表現できますが、その一方で、とても単純な補間の補間の補間の……というふうにも説明できます。これがベジエ曲線のおもしろいところです。これはまた、ベジェ曲線は「本当の数学」で見る関数を調べたり微分を調べたり、あらゆる方法でことも可能ですし、「機械的」な組み立て操作として見る例えば、ベジエ曲線は組み立てに使う点の間からは決してはみ出ないということがわかりますことも可能だということを意味しています。
それでは、もう少し詳しくベジエ曲線を見ていきましょう。数学的な表現やそこから導かれる性質、さらには、ベジエ曲線に対して/ベジエ曲線を使ってできるさまざまな内容についてです。

View File

@@ -0,0 +1,28 @@
# 什么构成了贝塞尔曲线?
操作点的移动,看看曲线的变化,可能让你感受到了贝塞尔曲线是如何表现的。但贝塞尔曲线究竟*是*什么呢?有两种方式来解释贝塞尔曲线,并且可以证明它们完全相等,但是其中一种用到了复杂的数学,另外一种比较简单。所以...我们先从简单的开始吧:
贝塞尔曲线是[线性插值](https://zh.wikipedia.org/wiki/%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC)的结果。这听起来很复杂,但你在很小的时候就做过线性插值:当你指向两个物体中的另外一个物体时,你就用到了线性插值。它就是很简单的“选出两点之间的一个点”。
如果我们知道两点之间的距离并想找出离第一个点20%间距的一个新的点(也就是离第二个点80%的间距),我们可以通过简单的计算来得到:
\[
Given \left (
\begin{aligned}
p_1 &= some\ point \\
p_2 &= some\ other\ point \\
distance &= (p_2 - p_1) \\
ratio &= \frac{percentage}{100} \\
\end{aligned}
\right ),\ our\ new\ point = p_1 + distance \cdot ratio
\]
让我们来通过实际操作看一下:下面的图形都是可交互的,因此你可以通过上下键来增加或减少插值距离,来观察图形的变化。我们从三个点构成的两条线段开始。通过对各条线段进行线性插值得到两个点,对点之间的线段再进行线性插值,产生一个新的点。最终这些点——所有的点都可以通过选取不同的距离插值产生——构成了贝塞尔曲线
<graphics-element title="Linear Interpolation leading to Bézier curves" width="825" height="275" src="./chapters/whatis/interpolation.js"></graphics-element>
这为我们引出了复杂的数学:微积分。
虽然我们刚才好像没有用到这个,我们实际上只是逐步地画了一条二次曲线,而不是一次画好。贝塞尔曲线的一个很棒的特性就是它们可以通过多项式方程表示,也可以用很简单的插值形式表示。因此,反过来说,我们可以基于“真正的数学”(检查方程式,导数之类的东西),也可以通过观察曲线的“机械”构成(比如说,可以得知曲线永远不会延伸超过我们用来构造它的点),来看看这些曲线能够做什么。
让我们从更深的层次来观察贝塞尔曲线。看看它们的数学表达式,从这些表达式衍生得到的属性,以及我们可以对贝塞尔曲线做的事。

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -81,17 +81,14 @@
>Help translate this content!</a >Help translate this content!</a
></span ></span
> >
<nav aria-labelledby="toc">
<h1 id="toc">Table of Contents</h1>
<li><a href="#introduction">A lightning introduction</a></li>
<li><a href="#whatis">So what makes a Bézier Curve?</a></li>
</nav>
</header> </header>
<main> <main>
<section id="toc">
<h1>Table of Contents</h1>
<ol>
<li><a href="#introduction">A lightning introduction</a></li>
<li><a href="#whatis">So what makes a Bézier Curve?</a></li>
</ol>
</section>
<section id="preface"> <section id="preface">
<section id="preface"> <section id="preface">
<h1>Preface</h1> <h1>Preface</h1>
@@ -436,14 +433,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/quadratic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/quadratic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
<graphics-element <graphics-element
title="A cubic Bézier curve" title="A cubic Bézier curve"
width="275" width="275"
@@ -452,13 +449,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/cubic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/cubic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
</div> </div>
<p> <p>
@@ -498,9 +496,10 @@
</p> </p>
<img <img
className="LaTeX SVG" className="LaTeX SVG"
src="images/latex/0ee04e4056391f945c1c21c1174a03b5.svg" src="images/latex/b5aa26284ba3df74970a95cb047a841d.svg"
width="507px" width="501px"
height="103px" height="103px"
loading="lazy"
/> />
<p> <p>
So let's look at that in action: the following graphic is So let's look at that in action: the following graphic is
@@ -520,13 +519,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/whatis/interpolation.png"
width="825" width="825"
height="275" height="275"
src="./chapters/whatis/interpolation.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
<p>And that brings us to the complicated maths: calculus.</p> <p>And that brings us to the complicated maths: calculus.</p>
<p> <p>

View File

@@ -14,10 +14,7 @@
<!-- opengraph information --> <!-- opengraph information -->
<meta property="og:title" content="{{ title }}" /> <meta property="og:title" content="{{ title }}" />
<meta <meta property="og:image" content="https://pomax.github.io/bezierinfo/images/og-image.png" />
property="og:image"
content="https://pomax.github.io/bezierinfo/images/og-image.png"
/>
<meta property="og:type" content="text" /> <meta property="og:type" content="text" />
<meta property="og:url" content="https://pomax.github.io/bezierinfo" /> <meta property="og:url" content="https://pomax.github.io/bezierinfo" />
<meta property="og:description" content="{{ description }}" /> <meta property="og:description" content="{{ description }}" />
@@ -32,10 +29,7 @@
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@TheRealPomax" /> <meta name="twitter:site" content="@TheRealPomax" />
<meta name="twitter:creator" content="@TheRealPomax" /> <meta name="twitter:creator" content="@TheRealPomax" />
<meta <meta name="twitter:image" content="https://pomax.github.io/bezierinfo/images/og-image.png" />
name="twitter:image"
content="https://pomax.github.io/bezierinfo/images/og-image.png"
/>
<meta name="twitter:url" content="https://pomax.github.io/bezierinfo" /> <meta name="twitter:url" content="https://pomax.github.io/bezierinfo" />
<meta name="twitter:description" content="{{ description }}" /> <meta name="twitter:description" content="{{ description }}" />
@@ -43,12 +37,7 @@
<script src="./lib/site/referrer.js" type="module" async></script> <script src="./lib/site/referrer.js" type="module" async></script>
<!-- the part that makes interactive graphics work: an HTML5 <graphics-element> custom element --> <!-- the part that makes interactive graphics work: an HTML5 <graphics-element> custom element -->
<script <script src="./lib/custom-element/graphics-element.js" type="module" async defer></script>
src="./lib/custom-element/graphics-element.js"
type="module"
async
defer
></script>
<link rel="stylesheet" href="./lib/custom-element/graphics-element.css" /> <link rel="stylesheet" href="./lib/custom-element/graphics-element.css" />
<!-- page styling --> <!-- page styling -->
@@ -64,16 +53,13 @@
{{ langSwitcher }} {{ langSwitcher }}
</ul> </ul>
<span>{{ langHelpLabel }}</span> <span>{{ langHelpLabel }}</span>
<nav aria-labelledby="toc">
<h1 id="toc">{{ tocLabel }}</h1>
{{ toc }}
</nav>
</header> </header>
<main> <main>
<section id="toc">
<h1>{{ tocLabel }}</h1>
<ol>
{{ toc }}
</ol>
</section>
<section id="preface"> <section id="preface">
{{ preface }} {{ preface }}
</section> </section>

View File

@@ -83,17 +83,16 @@
>Help translate this content!</a >Help translate this content!</a
></span ></span
> >
<nav aria-labelledby="toc">
<h1 id="toc">目次</h1>
<li><a href="#introduction">バッとした導入</a></li>
<li>
<a href="#whatis">ではベジエ曲線はどうやってできるのでしょう?</a>
</li>
</nav>
</header> </header>
<main> <main>
<section id="toc">
<h1>目次</h1>
<ol>
<li><a href="#introduction">バッとした導入</a></li>
<li><a href="#whatis">So what makes a Bézier Curve?</a></li>
</ol>
</section>
<section id="preface"> <section id="preface">
<section id="preface"> <section id="preface">
<h1>まえがき</h1> <h1>まえがき</h1>
@@ -352,14 +351,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/quadratic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/quadratic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
<graphics-element <graphics-element
title="3次のベジエ曲線" title="3次のベジエ曲線"
width="275" width="275"
@@ -368,13 +367,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/cubic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/cubic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
</div> </div>
<p> <p>
@@ -386,45 +386,28 @@
</p> </p>
</section> </section>
<section id="whatis"> <section id="whatis">
<h1>So what makes a Bézier Curve?</h1> <h1>ではベジエ曲線はどうやってできるのでしょう?</h1>
<p> <p>
Playing with the points for curves may have given you a feel for how ベジエ曲線がどのように動くのか、点を触ってみて感覚が摑めたかもしれません。では、実際のところベジエ曲線<em>とは</em>いったい何でしょうかこれを説明する方法は2通りありますが、どちらの説明でも行き着く先はまったく同じです。一方は複雑な数学を使うのに対し、もう一方はとても簡単です。というわけで……簡単な説明の方から始めましょう。
Bézier curves behave, but what <em>are</em> Bézier curves, really?
There are two ways to explain what a Bézier curve is, and they turn
out to be the entirely equivalent, but one of them uses complicated
maths, and the other uses really simple maths. So... let's start
with the simple explanation:
</p> </p>
<p> <p>
Bézier curves are the result of ベジエ曲線は、<a
<a href="https://en.wikipedia.org/wiki/Linear_interpolation" href="https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E8%A3%9C%E9%96%93"
>linear interpolations</a >線形補間</a
>. That sounds complicated but you've been doing linear >の結果です。というと難しそうに聞こえますが、誰でも幼い頃から線形補間をやってきています。例えば、何か2つのものの間を指し示すときには、いつも線形補間を行っています。線形補間とは、単純に「2点の間から点を得る」ことなのです。
interpolation since you were very young: any time you had to point
at something between two other things, you've been applying linear
interpolation. It's simply "picking a point between two points".
</p> </p>
<p> <p>
If we know the distance between those two points, and we want a new 例えば、2点間の距離がわかっているとして、一方の点から距離の20%だけ離れたすなわち、もう一方の点から80%離れた)新しい点を求めたい場合、次のようにとても簡単に計算できます。
point that is, say, 20% the distance away from the first point (and
thus 80% the distance away from the second point) then we can
compute that really easily:
</p> </p>
<img <img
className="LaTeX SVG" className="LaTeX SVG"
src="images/latex/0ee04e4056391f945c1c21c1174a03b5.svg" src="images/latex/4df088f01d0fd4de84a50bbc2e25f8a7.svg"
width="507px" width="216px"
height="103px" height="92px"
loading="lazy"
/> />
<p> <p>
So let's look at that in action: the following graphic is では、実際に見てみましょう。下の図はインタラクティブになっています。上下キーで補間の比率が増減しますので、どうなるか確かめてみましょう。最初に3点があり、それを結んで2本の直線が引かれています。この直線の上でそれぞれ線形補間を行うと、2つの点が得られます。この2点の間でさらに線形補間を行うと、1つの点を得ることができます。そして、あらゆる比率に対して同様に点を求め、それをすべて集めると、このようにベジエ曲線ができるのです。
interactive in that you can use your up and down arrow keys to
increase or decrease the interpolation ratio, to see what happens.
We start with three points, which gives us two lines. Linear
interpolation over those lines gives us two points, between which we
can again perform linear interpolation, yielding a single point. And
that point —and all points we can form in this way for all ratios
taken together— form our Bézier curve:
</p> </p>
<graphics-element <graphics-element
title="Linear Interpolation leading to Bézier curves" title="Linear Interpolation leading to Bézier curves"
@@ -434,31 +417,21 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/whatis/interpolation.png"
width="825" width="825"
height="275" height="275"
src="./chapters/whatis/interpolation.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
<p>And that brings us to the complicated maths: calculus.</p> <p>また、これが複雑な方の数学につながっていきます。微積分です。</p>
<p> <p>
While it doesn't look like that's what we've just done, we actually いま上で行ったものとは似つかないように思えますが、実はあれは2次曲線を描いていたのです。ただし一発で描きあげるのではなく、手順を追って描いていきました。ベジエ曲線は多項式関数で表現できますが、その一方で、とても単純な補間の補間の補間の……というふうにも説明できます。これがベジエ曲線のおもしろいところです。これはまた、ベジェ曲線は「本当の数学」で見る関数を調べたり微分を調べたり、あらゆる方法でことも可能ですし、「機械的」な組み立て操作として見る例えば、ベジエ曲線は組み立てに使う点の間からは決してはみ出ないということがわかりますことも可能だということを意味しています。
just drew a quadratic curve, in steps, rather than in a single go.
One of the fascinating parts about Bézier curves is that they can
both be described in terms of polynomial functions, as well as in
terms of very simple interpolations of interpolations of [...].
That, in turn, means we can look at what these curves can do based
on both "real maths" (by examining the functions, their derivatives,
and all that stuff), as well as by looking at the "mechanical"
composition (which tells us, for instance, that a curve will never
extend beyond the points we used to construct it).
</p> </p>
<p> <p>
So let's start looking at Bézier curves a bit more in depth: their それでは、もう少し詳しくベジエ曲線を見ていきましょう。数学的な表現やそこから導かれる性質、さらには、ベジエ曲線に対して/ベジエ曲線を使ってできるさまざまな内容についてです。
mathematical expressions, the properties we can derive from them,
and the various things we can do to, and with, Bézier curves.
</p> </p>
</section> </section>
</section> </section>

View File

@@ -1,36 +1,20 @@
import marked from "marked"; import marked from "marked";
import latexToSVG from "./latex/latex-to-svg.js"; import latexToSVG from "./latex/latex-to-svg.js";
import localeStrings from "../../locale-strings.js";
import nunjucks from "nunjucks"; import nunjucks from "nunjucks";
nunjucks.configure(".", { autoescape: false }); nunjucks.configure(".", { autoescape: false });
/** /**
* ...docs go here... * ...docs go here...
*/ */
export default async function convertMarkDown(markdown) { export default async function convertMarkDown(chapter, locale, markdown) {
// preprocess marrkdown to extract LaTeX sections markdown = injectGraphicsFallback(locale, markdown);
let latexSection = 0,
pos = -1,
data = markdown,
latex = {},
startmark = `<script type="text/latex">`,
endmark = `</script>`;
do { const { data, latex } = extractLaTeX(markdown);
pos = data.indexOf(startmark);
if (pos !== -1) {
let endpos = data.indexOf(endmark, pos) + endmark.length;
let key = `latex${latexSection++}`;
latex[key] = data.substring(
pos + startmark.length,
endpos - endmark.length
);
data = `${data.slice(0, pos)}{{ ${key} }}${data.slice(endpos)}`;
}
} while (pos !== -1);
await Promise.all( await Promise.all(
Object.keys(latex).map(async (key) => { Object.keys(latex).map(async (key, pos) => {
const svg = await latexToSVG(latex[key]); const svg = await latexToSVG(latex[key], chapter, locale, pos + 1);
return (latex[key] = svg); return (latex[key] = svg);
}) })
); );
@@ -49,3 +33,58 @@ export default async function convertMarkDown(markdown) {
return nunjucks.renderString(converted, latex); return nunjucks.renderString(converted, latex);
} }
/**
*
*/
function injectGraphicsFallback(locale, markdown) {
let pos = -1,
data = markdown,
startmark = `<graphics-element`,
endmark = `</graphics-element>`;
do {
pos = data.indexOf(startmark, pos);
if (pos !== -1) {
let endpos = data.indexOf(endmark, pos) + endmark.length;
let slice = data.slice(pos, endpos);
let updated = slice.replace(/width="([^"]+)"\s+height="([^"]+)"\s+src="([^"]+)"\s*>/, (_, width, height, src) =>
`width="${width}" height="${height}" src="${src}">
<fallback-image>
<img width="${width}" height="${height}" src="${src.replace(`.js`, `.png`)}" loading="lazy">
${ localeStrings.disabledMessage[locale] }
</fallback-image>`);
data = data.replace(slice, updated);
pos += updated.length;
}
} while (pos !== -1);
return data;
}
/**
* ...
*/
function extractLaTeX(markdown) {
let latexSection = 0,
pos = -1,
data = markdown,
latex = {},
startmark = `\\[`,
endmark = `\\]`;
do {
pos = data.indexOf(startmark);
if (pos !== -1) {
let endpos = data.indexOf(endmark, pos) + endmark.length;
let key = `latex${latexSection++}`;
latex[key] = data.substring(
pos + startmark.length,
endpos - endmark.length
);
data = `${data.slice(0, pos)}{{ ${key} }}${data.slice(endpos)}`;
}
} while (pos !== -1);
return { data, latex };
}

View File

@@ -5,7 +5,7 @@ import { execSync } from "child_process";
import cleanUp from "./cleanup.js"; import cleanUp from "./cleanup.js";
const moduleURL = new URL(import.meta.url); const moduleURL = new URL(import.meta.url);
const __dirname = path.dirname(moduleURL.href.replace(`file:///`,``)); const __dirname = path.dirname(moduleURL.href.replace(`file:///`, ``));
const baseDir = path.join(__dirname, `..`, `..`, `..`, `images`, `latex`); const baseDir = path.join(__dirname, `..`, `..`, `..`, `images`, `latex`);
fs.ensureDirSync(baseDir); fs.ensureDirSync(baseDir);
@@ -13,70 +13,111 @@ fs.ensureDirSync(baseDir);
const sourceDir = path.join(baseDir, `source`); const sourceDir = path.join(baseDir, `source`);
fs.ensureDirSync(sourceDir); fs.ensureDirSync(sourceDir);
/**
* This converts a latex block into a .svg file by running it through
* XeLaTeX, and then converting the resulting PDF into an SVG image
* in the ./images directory.
*
* The function returns an <img> tag with the src pointing at the
* right file, and the width and height attributes prespecified,
* so that the document won't constantly reflow as it loads images
* in.
*/
export default async function latexToSVG(latex, chapter, locale, block) {
const hash = createHash(`md5`).update(latex).digest(`hex`);
const TeXfilename = path.join(sourceDir, hash + `.tex`);
const SVGfilename = path.resolve(
path.join(path.dirname(TeXfilename), `..`, hash + `.svg`)
);
if (!fs.existsSync(SVGfilename)) {
const PDFfilename = TeXfilename.replace(`.tex`, `.pdf`);
const PDFfilenameCropped = TeXfilename.replace(`.tex`, `-crop.pdf`);
fs.writeFileSync(
TeXfilename,
[
`\\documentclass[12pt]{article}`,
`\\usepackage[paperwidth=12in, paperheight=12in]{geometry}`,
`\\pagestyle{empty}`,
`\\usepackage{color}`,
`\\usepackage{amsmath}`,
`\\usepackage{unicode-math}`,
`\\setmainfont[Ligatures=TeX]{TeX Gyre Pagella}`,
`\\setmathfont{TeX Gyre Pagella Math}`,
`\\begin{document}`,
`\\[`,
cleanUp(latex),
`\\]`,
`\\end{document}`,
].join(`\n`)
);
// Finally: run the conversion
console.log(
`- running xelatex for block [${chapter}:${locale}:${block}] (${hash}.tex)`
);
runCmd(
`xelatex -output-directory "${path.dirname(
TeXfilename
)}" "${TeXfilename}"`,
hash
);
process.stdout.write(` - cropping PDF to document content: `);
try {
runCmd(`pdfcrop "${PDFfilename}"`, hash);
console.log(``);
process.stdout.write(` - converting cropped PDF to SVG: `);
try {
runCmd(`pdf2svg "${PDFfilenameCropped}" "${SVGfilename}"`, hash);
console.log(``);
process.stdout.write(` - cleaning up SVG: `);
try {
runCmd(`npx svgo "${SVGfilename}"`, hash);
console.log(``);
} catch (e) {
console.log(``);
console.error(e);
}
} catch (e) {
console.log(``);
console.error(e);
}
} catch (e) {
console.log(``);
console.error(e);
}
}
// Make sure we hardcode the size of this LaTeX SVG image, because we absolutely
// do not want the page to resize in any possible noticable way if we can help it.
var svg = fs.readFileSync(SVGfilename).toString(`utf8`);
var vb = svg.match(/viewBox="([^"]+)"/)[1].split(/\s+/);
// The SVG contains values in "pt" units, but to maximise legibility we convert
// these to "rem" instead, so that formulae are always sized based on the font
// around them, rather than being sized independently of the document text.
// Base browser sizes are 16pt so the conversion factor is 4/3.
var w = Math.round(((parseFloat(vb[2]) - parseFloat(vb[0])) * 4) / 3);
var h = Math.round(((parseFloat(vb[3]) - parseFloat(vb[1])) * 4) / 3);
return `<img className="LaTeX SVG" src="images/latex/${path.basename(
SVGfilename
)}" width="${Math.round(w)}px" height="${Math.round(h)}px" loading="lazy">`;
}
// This function really needs better stdio capture, // This function really needs better stdio capture,
// so it can report _what went wrong_ when xelatex fails. // so it can report _what went wrong_ when xelatex fails.
function runCmd(cmd, hash) { function runCmd(cmd, hash) {
try { try {
execSync(cmd); //, { stdio: 'inherit' }); execSync(cmd); //, { stdio: 'inherit' });
} catch (e) { } catch (e) {
console.error("could not run cmd: ", cmd); console.error(`could not run cmd: ${cmd}`);
console.log("hash:\n", hash); console.log(`hash:\n${hash}`);
process.exit(1); process.exit(1);
} }
} }
export default async function latexToSVG(latex) {
const hash = createHash(`md5`).update(latex).digest(`hex`);
const TeXfilename = path.join(sourceDir, hash + ".tex");
const SVGfilename = path.resolve(path.join(path.dirname(TeXfilename), '..', hash + ".svg"));
if (!fs.existsSync(SVGfilename)) {
const PDFfilename = TeXfilename.replace(".tex",".pdf");
const PDFfilenameCropped = TeXfilename.replace(".tex","-crop.pdf");
fs.writeFileSync(TeXfilename, [
`\\documentclass[12pt]{article}`,
`\\usepackage[paperwidth=12in, paperheight=12in]{geometry}`,
`\\pagestyle{empty}`,
`\\usepackage{color}`,
`\\usepackage{amsmath}`,
`\\usepackage{unicode-math}`,
`\\setmainfont[Ligatures=TeX]{TeX Gyre Pagella}`,
`\\setmathfont{TeX Gyre Pagella Math}`,
`\\begin{document}`,
`\\[`,
cleanUp(latex),
`\\]`,
`\\end{document}`
].join(`\n`));
// Finally: run the conversion
console.log("- running xelatex on " + hash + ".tex");
runCmd(`xelatex -output-directory "${path.dirname(TeXfilename)}" "${TeXfilename}"`, hash);
console.log("- cropping PDF to document content");
runCmd(`pdfcrop "${ PDFfilename }"`, hash);
console.log("- converting cropped PDF to SVG");
runCmd(`pdf2svg "${ PDFfilenameCropped }" "${ SVGfilename }"`, hash);
console.log("- cleaning up SVG");
runCmd(`npx svgo "${ SVGfilename }"`, hash);
}
// Make sure we hardcode the size of this LaTeX SVG image, because we absolutely
// do not want the page to resize in any possible noticable way if we can help it.
var svg = fs.readFileSync(SVGfilename).toString(`utf8`);
var vb = svg.match(/viewBox="([^"]+)"/)[1].split(/\s+/);
// The SVG contains values in "pt" units, but to maximise legibility we convert
// these to "rem" instead, so that formulae are always sized based on the font
// around them, rather than being sized independently of the document text.
// Base browser sizes are 16pt so the conversion factor is 4/3.
var w = Math.round((parseFloat(vb[2]) - parseFloat(vb[0])) * 4/3);
var h = Math.round((parseFloat(vb[3]) - parseFloat(vb[1])) * 4/3);
return `<img className="LaTeX SVG" src="images/latex/${path.basename(SVGfilename)}" width="${Math.round(w)}px" height="${Math.round(h)}px">`;
};

View File

@@ -57,7 +57,7 @@ export default async function processLocale(locale, chapterFiles) {
const replaced = nunjucks.renderString(markdown, { const replaced = nunjucks.renderString(markdown, {
disableMessage: `<span>${localeStrings.disabledMessage[locale]}</span>`, disableMessage: `<span>${localeStrings.disabledMessage[locale]}</span>`,
}); });
const converted = await convertMarkDown(replaced); const converted = await convertMarkDown(chapter, locale, replaced);
chapters[chapter] = converted; chapters[chapter] = converted;
}) })
); );

View File

@@ -83,17 +83,14 @@
>Help translate this content!</a >Help translate this content!</a
></span ></span
> >
<nav aria-labelledby="toc">
<h1 id="toc">目录</h1>
<li><a href="#introduction">简单介绍</a></li>
<li><a href="#whatis">什么构成了贝塞尔曲线?</a></li>
</nav>
</header> </header>
<main> <main>
<section id="toc">
<h1>目录</h1>
<ol>
<li><a href="#introduction">简单介绍</a></li>
<li><a href="#whatis">So what makes a Bézier Curve?</a></li>
</ol>
</section>
<section id="preface"> <section id="preface">
<section id="preface"> <section id="preface">
<h1>序言</h1> <h1>序言</h1>
@@ -340,14 +337,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/quadratic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/quadratic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
<graphics-element <graphics-element
title="三次贝塞尔曲线" title="三次贝塞尔曲线"
width="275" width="275"
@@ -356,13 +353,14 @@
> >
<fallback-image> <fallback-image>
<img <img
src="./chapters/introduction/cubic.png"
width="275" width="275"
height="275" height="275"
src="./chapters/introduction/cubic.png"
loading="lazy"
/> />
<span>Scripts are disabled. Showing fallback image.</span> Scripts are disabled. Showing fallback image.
</fallback-image> </fallback-image></graphics-element
</graphics-element> >
</div> </div>
<p> <p>
@@ -372,79 +370,52 @@
</p> </p>
</section> </section>
<section id="whatis"> <section id="whatis">
<h1>So what makes a Bézier Curve?</h1> <h1>什么构成了贝塞尔曲线?</h1>
<p> <p>
Playing with the points for curves may have given you a feel for how 操作点的移动,看看曲线的变化,可能让你感受到了贝塞尔曲线是如何表现的。但贝塞尔曲线究竟<em></em>什么呢?有两种方式来解释贝塞尔曲线,并且可以证明它们完全相等,但是其中一种用到了复杂的数学,另外一种比较简单。所以...我们先从简单的开始吧:
Bézier curves behave, but what <em>are</em> Bézier curves, really?
There are two ways to explain what a Bézier curve is, and they turn
out to be the entirely equivalent, but one of them uses complicated
maths, and the other uses really simple maths. So... let's start
with the simple explanation:
</p> </p>
<p> <p>
Bézier curves are the result of 贝塞尔曲线是<a
<a href="https://en.wikipedia.org/wiki/Linear_interpolation" href="https://zh.wikipedia.org/wiki/%E7%BA%BF%E6%80%A7%E6%8F%92%E5%80%BC"
>linear interpolations</a >线性插值</a
>. That sounds complicated but you've been doing linear >的结果。这听起来很复杂,但你在很小的时候就做过线性插值:当你指向两个物体中的另外一个物体时,你就用到了线性插值。它就是很简单的“选出两点之间的一个点”。
interpolation since you were very young: any time you had to point
at something between two other things, you've been applying linear
interpolation. It's simply "picking a point between two points".
</p> </p>
<p> <p>
If we know the distance between those two points, and we want a new 如果我们知道两点之间的距离并想找出离第一个点20%间距的一个新的点(也就是离第二个点80%的间距),我们可以通过简单的计算来得到:
point that is, say, 20% the distance away from the first point (and
thus 80% the distance away from the second point) then we can
compute that really easily:
</p> </p>
<img <img
className="LaTeX SVG" className="LaTeX SVG"
src="images/latex/0ee04e4056391f945c1c21c1174a03b5.svg" src="images/latex/b5aa26284ba3df74970a95cb047a841d.svg"
width="507px" width="501px"
height="103px" height="103px"
loading="lazy"
/> />
<p> <p>
So let's look at that in action: the following graphic is 让我们来通过实际操作看一下:下面的图形都是可交互的,因此你可以通过上下键来增加或减少插值距离,来观察图形的变化。我们从三个点构成的两条线段开始。通过对各条线段进行线性插值得到两个点,对点之间的线段再进行线性插值,产生一个新的点。最终这些点——所有的点都可以通过选取不同的距离插值产生——构成了贝塞尔曲线
interactive in that you can use your up and down arrow keys to
increase or decrease the interpolation ratio, to see what happens. <graphics-element
We start with three points, which gives us two lines. Linear title="Linear Interpolation leading to Bézier curves"
interpolation over those lines gives us two points, between which we width="825"
can again perform linear interpolation, yielding a single point. And height="275"
that point —and all points we can form in this way for all ratios src="./chapters/whatis/interpolation.js"
taken together— form our Bézier curve: >
<fallback-image>
<img
width="825"
height="275"
src="./chapters/whatis/interpolation.png"
loading="lazy"
/>
Scripts are disabled. Showing fallback image.
</fallback-image></graphics-element
>
</p> </p>
<graphics-element <p>这为我们引出了复杂的数学:微积分。</p>
title="Linear Interpolation leading to Bézier curves"
width="825"
height="275"
src="./chapters/whatis/interpolation.js"
>
<fallback-image>
<img
src="./chapters/whatis/interpolation.png"
width="825"
height="275"
/>
<span>Scripts are disabled. Showing fallback image.</span>
</fallback-image>
</graphics-element>
<p>And that brings us to the complicated maths: calculus.</p>
<p> <p>
While it doesn't look like that's what we've just done, we actually 虽然我们刚才好像没有用到这个,我们实际上只是逐步地画了一条二次曲线,而不是一次画好。贝塞尔曲线的一个很棒的特性就是它们可以通过多项式方程表示,也可以用很简单的插值形式表示。因此,反过来说,我们可以基于“真正的数学”(检查方程式,导数之类的东西),也可以通过观察曲线的“机械”构成(比如说,可以得知曲线永远不会延伸超过我们用来构造它的点),来看看这些曲线能够做什么。
just drew a quadratic curve, in steps, rather than in a single go.
One of the fascinating parts about Bézier curves is that they can
both be described in terms of polynomial functions, as well as in
terms of very simple interpolations of interpolations of [...].
That, in turn, means we can look at what these curves can do based
on both "real maths" (by examining the functions, their derivatives,
and all that stuff), as well as by looking at the "mechanical"
composition (which tells us, for instance, that a curve will never
extend beyond the points we used to construct it).
</p> </p>
<p> <p>
So let's start looking at Bézier curves a bit more in depth: their 让我们从更深的层次来观察贝塞尔曲线。看看它们的数学表达式,从这些表达式衍生得到的属性,以及我们可以对贝塞尔曲线做的事。
mathematical expressions, the properties we can derive from them,
and the various things we can do to, and with, Bézier curves.
</p> </p>
</section> </section>
</section> </section>