diff --git a/docs/chapters/control/content.en-GB.md b/docs/chapters/control/content.en-GB.md
index 55cea268..1786f622 100644
--- a/docs/chapters/control/content.en-GB.md
+++ b/docs/chapters/control/content.en-GB.md
@@ -5,9 +5,17 @@ Bézier curves are, like all "splines", interpolation functions. This means that
The following graphs show the interpolation functions for quadratic and cubic curves, with "S" being the strength of a point's contribution to the total sum of the Bézier function. Click-and-drag to see the interpolation percentages for each curve-defining point at a specific t value.
-
-
-
+
+
+
+
+
+
+
+
+
+
+
Also shown is the interpolation function for a 15th order Bézier function. As you can see, the start and end point contribute considerably more to the curve's shape than any other point in the control point set.
diff --git a/docs/chapters/control/content.ja-JP.md b/docs/chapters/control/content.ja-JP.md
index 82447736..ad7218a8 100644
--- a/docs/chapters/control/content.ja-JP.md
+++ b/docs/chapters/control/content.ja-JP.md
@@ -5,9 +5,17 @@
下のグラフは、2次ベジエ曲線や3次ベジエ曲線の補間関数を表しています。ここでSは、ベジエ関数全体に対しての、その点の寄与の大きさを示します。あるtにおいて、ベジエ曲線を定義する各点の補間率がどのようになっているのか、クリックドラッグをして確かめてみてください。
diff --git a/docs/chapters/decasteljau/decasteljau.js b/docs/chapters/decasteljau/decasteljau.js
index a3dc0360..192dddbb 100644
--- a/docs/chapters/decasteljau/decasteljau.js
+++ b/docs/chapters/decasteljau/decasteljau.js
@@ -1,28 +1,37 @@
-let curve;
-
setup() {
- curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
- setMovable(curve.points);
+ this.curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
+ setMovable(this.curve.points);
+ this.position = 0;
+ setSlider(`.slide-control`, v => this.setPosition(v));
+}
+
+setPosition(v) {
+ this.position = v;
}
draw() {
clear();
+ const curve = this.curve;
curve.drawSkeleton();
curve.drawCurve();
setStroke("rgb(200,100,100)");
- let dim = this.height;
- let t = this.cursor.x / dim;
- curve.drawStruts(t);
+ let t = this.position;
+ if (0 < t && t < 1) {
+ curve.drawStruts(t);
+ }
+
curve.drawPoints();
- let p = curve.get(t);
- circle(p.x, p.y, 5);
+ if (0 < t && t < 1) {
+ let p = curve.get(t);
+ circle(p.x, p.y, 5);
- let perc = (t*100)|0;
- t = perc/100;
- text(`Sequential interpolation for ${perc}% (t=${t})`, 10, 15);
+ let perc = (t*100)|0;
+ let rt = perc/100;
+ text(`Sequential interpolation for ${perc}% (t=${rt})`, 10, 15);
+ }
}
onMouseMove() {
diff --git a/docs/chapters/explanation/circle.js b/docs/chapters/explanation/circle.js
index ca282293..64eb804a 100644
--- a/docs/chapters/explanation/circle.js
+++ b/docs/chapters/explanation/circle.js
@@ -1,5 +1,10 @@
setup() {
this.step = 5;
+ setSlider(`.slide-control`, v => this.setStep(v));
+}
+
+setStep(v) {
+ this.step = v;
}
draw() {
@@ -36,28 +41,3 @@ draw() {
}
}
}
-
-onKeyDown() {
- const key = this.keyboard.currentKey;
- if (key === `ArrowUp`) { this.step += 0.1; }
- if (key === `ArrowDown`) { this.step -= 0.1; }
- if (this.step < 1) this.step = 1;
- redraw();
-}
-
-onMouseDown() {
- this.mark = this.cursor.y;
-}
-
-onMouseUp() {
- this.mark = false;
-}
-
-onMouseMove() {
- if (this.mark) {
- let diff = this.mark - this.cursor.y,
- mapped = map(diff, -this.height/2, this.height/2, 0, 10, true);
- this.step = mapped;
- redraw();
- }
-}
diff --git a/docs/chapters/explanation/content.en-GB.md b/docs/chapters/explanation/content.en-GB.md
index 578c74a2..b6d088f8 100644
--- a/docs/chapters/explanation/content.en-GB.md
+++ b/docs/chapters/explanation/content.en-GB.md
@@ -39,9 +39,11 @@ Multiple functions, but only one variable. If we change the value for t,
There we go. x/y coordinates, linked through some mystery value t.
-So, parametric curves don't define a y coordinate in terms of an x coordinate, like normal functions do, but they instead link the values to a "control" variable. If we vary the value of t, then with every change we get two values, which we can use as (x,y) coordinates in a graph. The above set of functions, for instance, generates points on a circle: We can range t from negative to positive infinity, and the resulting (x,y) coordinates will always lie on a circle with radius 1 around the origin (0,0). If we plot it for t from 0 to 5, we get this (use your up and down arrow keys to change the plot end value):
+So, parametric curves don't define a y coordinate in terms of an x coordinate, like normal functions do, but they instead link the values to a "control" variable. If we vary the value of t, then with every change we get two values, which we can use as (x,y) coordinates in a graph. The above set of functions, for instance, generates points on a circle: We can range t from negative to positive infinity, and the resulting (x,y) coordinates will always lie on a circle with radius 1 around the origin (0,0). If we plot it for t from 0 to 5, we get this:
-
+
+
+
Bézier curves are just one out of the many classes of parametric functions, and are characterised by using the same base function for all of the output values. In the example we saw above, the x and y values were generated by different functions (one uses a sine, the other a cosine); but Bézier curves use the "binomial polynomial" for both the x and y outputs. So what are binomial polynomials?
diff --git a/docs/chapters/explanation/content.ja-JP.md b/docs/chapters/explanation/content.ja-JP.md
index 01aa1164..a0c299ea 100644
--- a/docs/chapters/explanation/content.ja-JP.md
+++ b/docs/chapters/explanation/content.ja-JP.md
@@ -37,9 +37,11 @@
きました。x/y座標です。謎の値tを通して繫がっています。
-というわけで、普通の関数ではy座標をx座標によって定義しますが、パラメトリック曲線ではそうではなく、座標の値を「制御」変数と結びつけます。tの値を変化させるたびに2つの値が変化するので、これをグラフ上の座標 (x,y)として使うことができます。例えば、先ほどの関数の組は円周上の点を生成します。負の無限大から正の無限大へとtを動かすと、得られる座標(x,y)は常に中心(0,0)・半径1の円の上に乗ります。tを0から5まで変化させてプロットした場合は、このようになります(上下キーでプロットの上限を変更できます)。
+というわけで、普通の関数ではy座標をx座標によって定義しますが、パラメトリック曲線ではそうではなく、座標の値を「制御」変数と結びつけます。tの値を変化させるたびに2つの値が変化するので、これをグラフ上の座標 (x,y)として使うことができます。例えば、先ほどの関数の組は円周上の点を生成します。負の無限大から正の無限大へとtを動かすと、得られる座標(x,y)は常に中心(0,0)・半径1の円の上に乗ります。tを0から5まで変化させてプロットした場合は、このようになります。
-
+
+
+
ベジエ曲線はパラメトリック関数の一種であり、どの次元に対しても同じ基底関数を使うという点で特徴づけられます。先ほどの例では、xの値とyの値とで異なる関数(正弦関数と余弦関数)を使っていましたが、ベジエ曲線ではxとyの両方で「二項係数多項式」を使います。では、二項係数多項式とは何でしょう?
diff --git a/docs/chapters/explanation/content.zh-CN.md b/docs/chapters/explanation/content.zh-CN.md
index c16ff7d9..5a416feb 100644
--- a/docs/chapters/explanation/content.zh-CN.md
+++ b/docs/chapters/explanation/content.zh-CN.md
@@ -37,9 +37,11 @@
好了,通过一些神秘的t值将x/y坐标系联系起来。
-所以,参数曲线不像一般函数那样,通过x坐标来定义y坐标,而是用一个“控制”变量将它们连接起来。如果改变t的值,每次变化时我们都能得到两个值,这可以作为图形中的(x,y)坐标。比如上面的方程组,生成位于一个圆上的点:我们可以使t在正负极值间变化,得到的输出(x,y)都会位于一个以原点(0,0)为中心且半径为1的圆上。如果我们画出t从0到5时的值,将得到如下图像(你可以用上下键来改变画的点和值):
+所以,参数曲线不像一般函数那样,通过x坐标来定义y坐标,而是用一个“控制”变量将它们连接起来。如果改变t的值,每次变化时我们都能得到两个值,这可以作为图形中的(x,y)坐标。比如上面的方程组,生成位于一个圆上的点:我们可以使t在正负极值间变化,得到的输出(x,y)都会位于一个以原点(0,0)为中心且半径为1的圆上。如果我们画出t从0到5时的值,将得到如下图像:
-
+
+
+
贝塞尔曲线是(一种)参数方程,并在它的多个维度上使用相同的基本方程。在上述的例子中x值和y值使用了不同的方程,与此不同的是,贝塞尔曲线的x和y都用了“二项多项式”。那什么是二项多项式呢?
diff --git a/docs/chapters/flattening/content.en-GB.md b/docs/chapters/flattening/content.en-GB.md
index 17222773..3c654042 100644
--- a/docs/chapters/flattening/content.en-GB.md
+++ b/docs/chapters/flattening/content.en-GB.md
@@ -4,8 +4,15 @@ We can also simplify the drawing process by "sampling" the curve at certain poin
We can do this is by saying "we want X segments", and then sampling the curve at intervals that are spaced such that we end up with the number of segments we wanted. The advantage of this method is that it's fast: instead of evaluating 100 or even 1000 curve coordinates, we can sample a much lower number and still end up with a curve that sort-of-kind-of looks good enough. The disadvantage of course is that we lose the precision of working with "the real curve", so we usually can't use the flattened for for doing true intersection detection, or curvature alignment.
-
-
+
+
+
+
+
+
+
+
+
Try clicking on the sketch and using your up and down arrow keys to lower the number of segments for both the quadratic and cubic curve. You'll notice that for certain curvatures, a low number of segments works quite well, but for more complex curvatures (try this for the cubic curve), a higher number is required to capture the curvature changes properly.
diff --git a/docs/chapters/flattening/content.ja-JP.md b/docs/chapters/flattening/content.ja-JP.md
index ef33b235..e59ae55d 100644
--- a/docs/chapters/flattening/content.ja-JP.md
+++ b/docs/chapters/flattening/content.ja-JP.md
@@ -4,8 +4,15 @@
例えば「X個の線分がほしい」場合には、分割数がそうなるようにサンプリング間隔を選び、曲線をサンプリングします。この方法の利点は速さです。曲線の座標を100個だの1000個だの計算するのではなく、ずっと少ない回数のサンプリングでも、十分きれいに見えるような曲線を作ることができるのです。欠点はもちろん、「本物の曲線」に比べて精度が損なわれてしまうことです。したがって、交点の検出や曲線の位置揃えを正しく行いたい場合には、平坦化した曲線は普通利用できません。
-
-
+
试着点击图形,并用上下键来降低二次曲线和三次曲线的分段数量。你会发现对某些曲率来说,数量少的分段也能做的很好,但对于复杂的曲率(在三次曲线上试试),足够多的分段才能很好地满足曲率的变化。
diff --git a/docs/chapters/flattening/cubic.js b/docs/chapters/flattening/cubic.js
index 84552746..25d6ba80 100644
--- a/docs/chapters/flattening/cubic.js
+++ b/docs/chapters/flattening/cubic.js
@@ -2,6 +2,11 @@ setup() {
this.steps = 8;
this.curve = Bezier.defaultCubic(this);
setMovable(this.curve.points);
+ setSlider(`.slide-control`, v => this.setStep(v));
+}
+
+setStep(v) {
+ this.steps = v;
}
draw() {
@@ -23,23 +28,6 @@ draw() {
text(`Flattened to ${this.steps} segments`, 10, 15);
}
-onKeyDown() {
- let key = this.keyboard.currentKey;
-
- if(key === `ArrowUp`) {
- this.steps++;
- }
-
- if(key === `ArrowDown`) {
- if(this.steps > 1) this.steps--;
- }
-
- redraw();
-}
-
onMouseMove() {
- if (this.cursor.down && !this.currentPoint) {
- this.steps = round( map(this.cursor.y, 0,this.height, 24, 1) );
- }
redraw();
}
diff --git a/docs/chapters/flattening/quadratic.js b/docs/chapters/flattening/quadratic.js
index 96e9e4e5..66570162 100644
--- a/docs/chapters/flattening/quadratic.js
+++ b/docs/chapters/flattening/quadratic.js
@@ -2,6 +2,11 @@ setup() {
this.steps = 4;
this.curve = Bezier.defaultQuadratic(this);
setMovable(this.curve.points);
+ setSlider(`.slide-control`, v => this.setStep(v));
+}
+
+setStep(v) {
+ this.steps = v;
}
draw() {
@@ -23,23 +28,6 @@ draw() {
text(`Flattened to ${this.steps} segments`, 10, 15);
}
-onKeyDown() {
- let key = this.keyboard.currentKey;
-
- if(key === `ArrowUp`) {
- this.steps++;
- }
-
- if(key === `ArrowDown`) {
- if(this.steps > 1) this.steps--;
- }
-
- redraw();
-}
-
onMouseMove() {
- if (this.cursor.down && !this.currentPoint) {
- this.steps = round( map(this.cursor.y, 0,this.height, 16, 1) );
- }
redraw();
}
diff --git a/docs/chapters/pointvectors3d/content.en-GB.md b/docs/chapters/pointvectors3d/content.en-GB.md
index 5ac64a75..46aa1514 100644
--- a/docs/chapters/pointvectors3d/content.en-GB.md
+++ b/docs/chapters/pointvectors3d/content.en-GB.md
@@ -24,7 +24,9 @@ Let's unpack that a little:
And then we're done, we found "the" normal vector for a 3D curve. Let's see what that looks like for a sample curve, shall we? You can move your cursor across the graphic from left to right, to show the normal at a point with a t value that is based on your cursor position: all the way on the left is 0, all the way on the right = 1, midway is t=0.5, etc:
-
+
+
+
However, if you've played with that graphic a bit, you might have noticed something odd. The normal seems to "suddenly twist around" around between t=0.5 and t=0.9... Why is doing that?
@@ -109,8 +111,10 @@ Ignoring comments, this is certainly more code than when we were just computing
Speaking of better looking, what does this actually look like? Let's revisit that earlier curve, but this time use rotation minimising frames rather than Frenet frames:
-
+
+
+
-That looks much better!
+That looks so much better!
For those reading along with the code: we don't even strictly speaking need a Frenet frame to start with: we could, for instance, treat the z-axis as our initial axis of rotation, so that our initial normal is **(0,0,1) × tangent**, and then take things from there, but having that initial "mathematically correct" frame so that the initial normal seems to line up based on the curve's orientation in 3D space is just nice.
diff --git a/docs/chapters/pointvectors3d/frenet.js b/docs/chapters/pointvectors3d/frenet.js
index 6e777bbc..3868d8b6 100644
--- a/docs/chapters/pointvectors3d/frenet.js
+++ b/docs/chapters/pointvectors3d/frenet.js
@@ -26,6 +26,11 @@ setup() {
this.cxz = new Bezier(this, points.map(p => projectXZ(p)));
this.cyz = new Bezier(this, points.map(p => projectYZ(p)));
this.t = 0;
+ setSlider(`.slide-control`, v => this.setPosition(v));
+}
+
+setPosition(v) {
+ this.t = v;
}
draw() {
@@ -134,24 +139,3 @@ drawVector(from, vec, length, color, label) {
});
text(label, from.x + txt.x, from.y + txt.y);
}
-
-onMouseMove() {
- this.t = constrain(
- map(this.cursor.x,0,this.width,-0.1, 1.1)
- ,0,1
- );
- redraw();
-}
-
-onKeyDown() {
- let key = this.keyboard.currentKey;
- if (key === `ArrowUp`) {
- this.t += 0.01;
- if (this.t > 1) this.t = 1;
- }
- if (key === `ArrowDown`) {
- this.t -= 0.01;
- if (this.t < 0) this.t = 0;
- }
- redraw();
-}
\ No newline at end of file
diff --git a/docs/chapters/pointvectors3d/rotation-minimizing.js b/docs/chapters/pointvectors3d/rotation-minimizing.js
index 4414c983..373c6772 100644
--- a/docs/chapters/pointvectors3d/rotation-minimizing.js
+++ b/docs/chapters/pointvectors3d/rotation-minimizing.js
@@ -26,6 +26,11 @@ setup() {
this.cxz = new Bezier(this, points.map(p => projectXZ(p)));
this.cyz = new Bezier(this, points.map(p => projectYZ(p)));
this.t = 0;
+ setSlider(`.slide-control`, v => this.setPosition(v));
+}
+
+setPosition(v) {
+ this.t = v;
}
draw() {
@@ -190,24 +195,3 @@ drawVector(from, vec, length, color, label) {
});
text(label, from.x + txt.x, from.y + txt.y);
}
-
-onMouseMove() {
- this.t = constrain(
- map(this.cursor.x,0,this.width,-0.1, 1.1)
- ,0,1
- );
- redraw();
-}
-
-onKeyDown() {
- let key = this.keyboard.currentKey;
- if (key === `ArrowUp`) {
- this.t += 0.01;
- if (this.t > 1) this.t = 1;
- }
- if (key === `ArrowDown`) {
- this.t -= 0.01;
- if (this.t < 0) this.t = 0;
- }
- redraw();
-}
\ No newline at end of file
diff --git a/docs/chapters/reordering/content.en-GB.md b/docs/chapters/reordering/content.en-GB.md
index 4b038637..9d523642 100644
--- a/docs/chapters/reordering/content.en-GB.md
+++ b/docs/chapters/reordering/content.en-GB.md
@@ -134,4 +134,7 @@ The steps taken here are:
And we're done: we now have an expression that lets us approximate an `n+1`th order curve with a lower `n`th order curve. It won't be an exact fit, but it's definitely a best approximation. So, let's implement these rules for raising and lowering curve order to a (semi) random curve, using the following graphic. Select the sketch, which has movable control points, and press your up and down arrow keys to raise or lower the curve order.
-
+
+
+
+
diff --git a/docs/chapters/reordering/reorder.js b/docs/chapters/reordering/reorder.js
index 2e08e2bb..3618dc06 100644
--- a/docs/chapters/reordering/reorder.js
+++ b/docs/chapters/reordering/reorder.js
@@ -9,6 +9,15 @@ setup() {
});
}
setMovable(points);
+ this.bindButtons();
+ }
+
+bindButtons() {
+ let rbutton = find(`.raise`);
+ if (rbutton) rbutton.listen(`click`, v => this.raise());
+
+ let lbutton = find(`.lower`);
+ if (lbutton) lbutton.listen(`click`, v => this.lower());
}
draw() {
@@ -63,6 +72,7 @@ raise() {
this.points = np;
resetMovable(this.points);
+ redraw();
}
lower() {
@@ -116,43 +126,9 @@ lower() {
}));
resetMovable(this.points);
-}
-
-onKeyDown() {
- const key = this.keyboard.currentKey;
- if (key === `ArrowUp`) {
- this.raise();
- }
- if (key === `ArrowDown`) {
- this.lower();
- }
redraw();
}
onMouseMove() {
- if (this.cursor.down && !this.currentPoint) {
- if (this.cursor.y < this.height/2) {
- this.lowerTimer = clearInterval(this.lowerTimer);
- if (!this.raiseTimer) {
- this.raiseTimer = setInterval(() => {
- this.raise();
- redraw();
- }, 1000);
- }
- }
- if (this.cursor.y > this.height/2) {
- this.raiseTimer = clearInterval(this.raiseTimer);
- if (!this.lowerTimer) {
- this.lowerTimer = setInterval(() => {
- this.lower();
- redraw();
- }, 1000);
- }
- }
- } else { redraw(); }
-}
-
-onMouseUp() {
- this.raiseTimer = clearInterval(this.raiseTimer);
- this.lowerTimer = clearInterval(this.lowerTimer);
+ redraw();
}
diff --git a/docs/chapters/splitting/content.en-GB.md b/docs/chapters/splitting/content.en-GB.md
index 932e1952..ae7e0616 100644
--- a/docs/chapters/splitting/content.en-GB.md
+++ b/docs/chapters/splitting/content.en-GB.md
@@ -2,7 +2,9 @@
Using de Casteljau's algorithm, we can also find all the points we need to split up a Bézier curve into two, smaller curves, which taken together form the original curve. When we construct de Casteljau's skeleton for some value `t`, the procedure gives us all the points we need to split a curve at that `t` value: one curve is defined by all the inside skeleton points found prior to our on-curve point, with the other curve being defined by all the inside skeleton points after our on-curve point.
-
+
+
+
diff --git a/docs/chapters/splitting/handler.js b/docs/chapters/splitting/handler.js
deleted file mode 100644
index 574a4cf8..00000000
--- a/docs/chapters/splitting/handler.js
+++ /dev/null
@@ -1,91 +0,0 @@
-module.exports = {
- setupCubic: function(api) {
- var curve = api.getDefaultCubic();
- api.setCurve(curve);
- api.forward = true;
- },
-
- drawSplit: function(api, curve) {
- api.setPanelCount(2);
- api.reset();
- api.drawSkeleton(curve);
- api.drawCurve(curve);
-
- var offset = {x:0, y:0};
- var t = 0.5;
- var pt = curve.get(0.5);
- var split = curve.split(t);
- api.drawCurve(split.left);
- api.drawCurve(split.right);
- api.setColor("red");
- api.drawCircle(pt,3);
-
- api.setColor("black");
- offset.x = api.getPanelWidth();
- api.drawLine({x:0,y:0},{x:0,y:api.getPanelHeight()}, offset);
-
- api.setColor("lightgrey");
- api.drawCurve(curve, offset);
- api.drawCircle(pt,4);
-
- offset.x -= 20;
- offset.y -= 20;
- api.drawSkeleton(split.left, offset, true);
- api.drawCurve(split.left, offset);
-
- offset.x += 40;
- offset.y += 40;
- api.drawSkeleton(split.right, offset, true);
- api.drawCurve(split.right, offset);
- },
-
- drawAnimated: function(api, curve) {
- api.setPanelCount(3);
- api.reset();
-
- var frame = api.getFrame();
- var interval = 5 * api.getPlayInterval();
- var t = (frame%interval)/interval;
- var forward = (frame%(2*interval)) < interval;
- if (forward) { t = t%1; } else { t = 1 - t%1; }
- var offset = {x:0, y:0};
-
- api.setColor("lightblue");
- api.drawHull(curve, t);
- api.drawSkeleton(curve);
- api.drawCurve(curve);
- var pt = curve.get(t);
- api.drawCircle(pt, 4);
-
- api.setColor("black");
- offset.x += api.getPanelWidth();
- api.drawLine({x:0,y:0},{x:0,y:api.getPanelHeight()}, offset);
-
- var split = curve.split(t);
-
- api.setColor("lightgrey");
- api.drawCurve(curve, offset);
- api.drawHull(curve, t, offset);
- api.setColor("black");
- api.drawCurve(split.left, offset);
- api.drawPoints(split.left.points, offset);
- api.setFill("black");
- api.text("Left side of curve split at t = " + (((100*t)|0)/100), {x: 10 + offset.x, y: 15 + offset.y});
-
- offset.x += api.getPanelWidth();
- api.drawLine({x:0,y:0},{x:0,y:api.getPanelHeight()}, offset);
-
- api.setColor("lightgrey");
- api.drawCurve(curve, offset);
- api.drawHull(curve, t, offset);
- api.setColor("black");
- api.drawCurve(split.right, offset);
- api.drawPoints(split.right.points, offset);
- api.setFill("black");
- api.text("Right side of curve split at t = " + (((100*t)|0)/100), {x: 10 + offset.x, y: 15 + offset.y});
- },
-
- togglePlay: function(evt, api) {
- if (api.playing) { api.pause(); } else { api.play(); }
- }
-};
diff --git a/docs/chapters/splitting/keepthisornot.txt b/docs/chapters/splitting/keepthisornot.txt
deleted file mode 100644
index dba06483..00000000
--- a/docs/chapters/splitting/keepthisornot.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-/*
-
-// const { left, right } = this.getLeftAndRight(this.t, this.curve.points);
-// const c1 = new Bezier(this, left);
-// const c2 = new Bezier(this, right);
-
-getLeftAndRight(t, points, left=[], right=[]) {
- if(points.length === 1) {
- left.push(points[0]);
- right.push(points[0]);
- return { left, right };
- }
-
- let newpoints = points.slice(1);
- for(let i=0; i this.setPosition(v));
+}
+
+setPosition(v) {
+ this.t = v;
}
draw() {
@@ -19,13 +24,13 @@ draw() {
setStroke(`black`);
line(0, 0, 0, this.height);
- this.drawSegment(c1, p);
+ this.drawSegment(c1, p, `first`);
translate(this.width/3, 0);
setStroke(`black`);
line(0, 0, 0, this.height);
- this.drawSegment(c2, p);
+ this.drawSegment(c2, p, `second`);
}
drawBasics(p) {
@@ -42,7 +47,7 @@ drawBasics(p) {
text(`The full curve, with struts`, 10, 15);
}
-drawSegment(c, p) {
+drawSegment(c, p, halfLabel) {
setStroke(`lightblue`);
this.curve.drawCurve(`lightblue`);
this.curve.drawSkeleton(`lightblue`);
@@ -53,28 +58,9 @@ drawSegment(c, p) {
setStroke(`red`);
circle(p.x, p.y, 3);
setFill(`black`)
- text(`The first half`, 10, 15);
-}
-
-onKeyDown() {
- let key = this.keyboard.currentKey;
-
- if(key === `ArrowUp`) {
- this.t += 0.01;
- }
-
- if(key === `ArrowDown`) {
- this.t -= 0.01
- }
-
- this.t = this.t < 0 ? 0 : this.t > 1 ? 1 : this.t;
-
- redraw();
+ text(`The ${halfLabel} half`, 10, 15);
}
onMouseMove() {
- if (this.cursor.down && !this.currentPoint) {
- this.t = map(this.cursor.y, 0,this.height, 0, 1);
- }
redraw();
}
diff --git a/docs/chapters/whatis/content.en-GB.md b/docs/chapters/whatis/content.en-GB.md
index 1f3bbf28..71647d47 100644
--- a/docs/chapters/whatis/content.en-GB.md
+++ b/docs/chapters/whatis/content.en-GB.md
@@ -19,7 +19,9 @@ Given \left (
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:
-
+
+
+
And that brings us to the complicated maths: calculus.
diff --git a/docs/chapters/whatis/content.ja-JP.md b/docs/chapters/whatis/content.ja-JP.md
index 0861d57f..89c15357 100644
--- a/docs/chapters/whatis/content.ja-JP.md
+++ b/docs/chapters/whatis/content.ja-JP.md
@@ -19,7 +19,9 @@
では、実際に見てみましょう。下の図はインタラクティブになっています。上下キーで補間の比率が増減しますので、どうなるか確かめてみましょう。最初に3点があり、それを結んで2本の直線が引かれています。この直線の上でそれぞれ線形補間を行うと、2つの点が得られます。この2点の間でさらに線形補間を行うと、1つの点を得ることができます。そして、あらゆる比率に対して同様に点を求め、それをすべて集めると、このようにベジエ曲線ができるのです。
-
+
+
+
また、これが複雑な方の数学につながっていきます。微積分です。
diff --git a/docs/chapters/whatis/content.zh-CN.md b/docs/chapters/whatis/content.zh-CN.md
index 9f271266..76445eee 100644
--- a/docs/chapters/whatis/content.zh-CN.md
+++ b/docs/chapters/whatis/content.zh-CN.md
@@ -19,7 +19,9 @@ Given \left (
让我们来通过实际操作看一下:下面的图形都是可交互的,因此你可以通过上下键来增加或减少插值距离,来观察图形的变化。我们从三个点构成的两条线段开始。通过对各条线段进行线性插值得到两个点,对点之间的线段再进行线性插值,产生一个新的点。最终这些点——所有的点都可以通过选取不同的距离插值产生——构成了贝塞尔曲线
:
-
+
+
+
这为我们引出了复杂的数学:微积分。
diff --git a/docs/chapters/whatis/interpolation.js b/docs/chapters/whatis/interpolation.js
index fa1fe9e4..8e631bad 100644
--- a/docs/chapters/whatis/interpolation.js
+++ b/docs/chapters/whatis/interpolation.js
@@ -2,6 +2,11 @@ setup() {
this.step = 25;
this.curve = Bezier.defaultQuadratic(this);
setMovable(this.curve.points);
+ setSlider(`.slide-control`, v => this.setStep(v))
+}
+
+setStep(v) {
+ this.step = 100 - v;
}
draw() {
@@ -101,41 +106,6 @@ drawCurveCoordinates() {
this.curve.drawPoints();
}
-onKeyDown() {
- this.mark = false;
- if (this.keyboard[`ArrowDown`]) {
- this.stepDown();
- }
- if (this.keyboard[`ArrowUp`]) {
- this.stepUp();
- }
- redraw();
-}
-
-stepDown(value = 1) {
- this.step -= value;
- if (this.step < 10) this.step = 10;
-}
-
-stepUp(value = 1) {
- this.step += value;
- if (this.step > 90) this.step = 90;
-}
-
-onMouseDown() {
- this.mark = this.cursor.y;
-}
-
-onMouseUp() {
- this.mark = false;
-}
-
onMouseMove() {
- if (this.mark && !this.currentPoint) {
- let diff = this.mark - this.cursor.y,
- mapped = map(diff, -this.height/2, this.height/2, 10, 90, true);
- this.step = mapped | 0;
- }
-
redraw();
}
diff --git a/docs/images/chapters/control/13bba6ecec2fa000c575813d0cda815c.png b/docs/images/chapters/control/13bba6ecec2fa000c575813d0cda815c.png
deleted file mode 100644
index aaad94f5..00000000
Binary files a/docs/images/chapters/control/13bba6ecec2fa000c575813d0cda815c.png and /dev/null differ
diff --git a/docs/images/chapters/control/15e8c8492908851ddde1cb35297326bb.png b/docs/images/chapters/control/15e8c8492908851ddde1cb35297326bb.png
deleted file mode 100644
index 9f2947b6..00000000
Binary files a/docs/images/chapters/control/15e8c8492908851ddde1cb35297326bb.png and /dev/null differ
diff --git a/docs/images/chapters/control/23dae5b8acf92135ea4463d8d0342190.png b/docs/images/chapters/control/23dae5b8acf92135ea4463d8d0342190.png
deleted file mode 100644
index 53f8a7f4..00000000
Binary files a/docs/images/chapters/control/23dae5b8acf92135ea4463d8d0342190.png and /dev/null differ
diff --git a/docs/images/chapters/control/53d95f337568a2108c525c559aa66e2b.png b/docs/images/chapters/control/53d95f337568a2108c525c559aa66e2b.png
new file mode 100644
index 00000000..bb0f9ac1
Binary files /dev/null and b/docs/images/chapters/control/53d95f337568a2108c525c559aa66e2b.png differ
diff --git a/docs/images/chapters/control/bf717f39221d5210e79ab8b0bcb38948.png b/docs/images/chapters/control/bf717f39221d5210e79ab8b0bcb38948.png
new file mode 100644
index 00000000..ca982e5c
Binary files /dev/null and b/docs/images/chapters/control/bf717f39221d5210e79ab8b0bcb38948.png differ
diff --git a/docs/images/chapters/control/f319958c931e9f28e41b889c9689c87e.png b/docs/images/chapters/control/f319958c931e9f28e41b889c9689c87e.png
new file mode 100644
index 00000000..14b5721d
Binary files /dev/null and b/docs/images/chapters/control/f319958c931e9f28e41b889c9689c87e.png differ
diff --git a/docs/images/chapters/decasteljau/425ee92efb13c790f63f8b3821327d3b.png b/docs/images/chapters/decasteljau/425ee92efb13c790f63f8b3821327d3b.png
deleted file mode 100644
index 19e750b4..00000000
Binary files a/docs/images/chapters/decasteljau/425ee92efb13c790f63f8b3821327d3b.png and /dev/null differ
diff --git a/docs/images/chapters/decasteljau/817f7e557caed67e173039d9032b3ab3.png b/docs/images/chapters/decasteljau/817f7e557caed67e173039d9032b3ab3.png
new file mode 100644
index 00000000..010218bd
Binary files /dev/null and b/docs/images/chapters/decasteljau/817f7e557caed67e173039d9032b3ab3.png differ
diff --git a/docs/images/chapters/explanation/1078bb1b1c8b7239aaa555e2d239e44d.png b/docs/images/chapters/explanation/1078bb1b1c8b7239aaa555e2d239e44d.png
new file mode 100644
index 00000000..4fa09b53
Binary files /dev/null and b/docs/images/chapters/explanation/1078bb1b1c8b7239aaa555e2d239e44d.png differ
diff --git a/docs/images/chapters/explanation/fdea63696e525033c5ea74fa8f90009a.png b/docs/images/chapters/explanation/fdea63696e525033c5ea74fa8f90009a.png
deleted file mode 100644
index 7871e858..00000000
Binary files a/docs/images/chapters/explanation/fdea63696e525033c5ea74fa8f90009a.png and /dev/null differ
diff --git a/docs/images/chapters/flattening/1a22ba71ef9a5aaf9c55e0b8c2f3f6e5.png b/docs/images/chapters/flattening/1a22ba71ef9a5aaf9c55e0b8c2f3f6e5.png
deleted file mode 100644
index 4893b3fc..00000000
Binary files a/docs/images/chapters/flattening/1a22ba71ef9a5aaf9c55e0b8c2f3f6e5.png and /dev/null differ
diff --git a/docs/images/chapters/flattening/4d4a648e8cac72a7041555ff885cbc2b.png b/docs/images/chapters/flattening/4d4a648e8cac72a7041555ff885cbc2b.png
deleted file mode 100644
index d292ab0d..00000000
Binary files a/docs/images/chapters/flattening/4d4a648e8cac72a7041555ff885cbc2b.png and /dev/null differ
diff --git a/docs/images/chapters/flattening/a8f7f97cb3b14c99e3cdf0c5283d7be4.png b/docs/images/chapters/flattening/a8f7f97cb3b14c99e3cdf0c5283d7be4.png
new file mode 100644
index 00000000..03bef0ec
Binary files /dev/null and b/docs/images/chapters/flattening/a8f7f97cb3b14c99e3cdf0c5283d7be4.png differ
diff --git a/docs/images/chapters/flattening/ffe43c40bea1277394df5ff82100a966.png b/docs/images/chapters/flattening/ffe43c40bea1277394df5ff82100a966.png
new file mode 100644
index 00000000..b1db83a8
Binary files /dev/null and b/docs/images/chapters/flattening/ffe43c40bea1277394df5ff82100a966.png differ
diff --git a/docs/images/chapters/pointvectors3d/769ab953d7f3542ab4c3a383f151b1bc.png b/docs/images/chapters/pointvectors3d/769ab953d7f3542ab4c3a383f151b1bc.png
new file mode 100644
index 00000000..81bc9aaf
Binary files /dev/null and b/docs/images/chapters/pointvectors3d/769ab953d7f3542ab4c3a383f151b1bc.png differ
diff --git a/docs/images/chapters/pointvectors3d/b11dfd6fef9931ac8715209785f63e0c.png b/docs/images/chapters/pointvectors3d/b11dfd6fef9931ac8715209785f63e0c.png
deleted file mode 100644
index f0f2c8eb..00000000
Binary files a/docs/images/chapters/pointvectors3d/b11dfd6fef9931ac8715209785f63e0c.png and /dev/null differ
diff --git a/docs/images/chapters/pointvectors3d/efd37ce3b7f4d8f084c287ec871c6b69.png b/docs/images/chapters/pointvectors3d/efd37ce3b7f4d8f084c287ec871c6b69.png
new file mode 100644
index 00000000..81bc9aaf
Binary files /dev/null and b/docs/images/chapters/pointvectors3d/efd37ce3b7f4d8f084c287ec871c6b69.png differ
diff --git a/docs/images/chapters/pointvectors3d/f5cf3e34415eccd1b03c4ef478862d44.png b/docs/images/chapters/pointvectors3d/f5cf3e34415eccd1b03c4ef478862d44.png
deleted file mode 100644
index f0f2c8eb..00000000
Binary files a/docs/images/chapters/pointvectors3d/f5cf3e34415eccd1b03c4ef478862d44.png and /dev/null differ
diff --git a/docs/images/chapters/reordering/4541eeb2113d81cbc0c0a56122570d48.png b/docs/images/chapters/reordering/4541eeb2113d81cbc0c0a56122570d48.png
deleted file mode 100644
index d1ced7c8..00000000
Binary files a/docs/images/chapters/reordering/4541eeb2113d81cbc0c0a56122570d48.png and /dev/null differ
diff --git a/docs/images/chapters/reordering/5ea06407f13c4b68a507c16d72fcb3e7.png b/docs/images/chapters/reordering/5ea06407f13c4b68a507c16d72fcb3e7.png
new file mode 100644
index 00000000..39083929
Binary files /dev/null and b/docs/images/chapters/reordering/5ea06407f13c4b68a507c16d72fcb3e7.png differ
diff --git a/docs/images/chapters/splitting/77d77c07832ad3adc3a3dec129a137bb.png b/docs/images/chapters/splitting/77d77c07832ad3adc3a3dec129a137bb.png
new file mode 100644
index 00000000..6467bf6a
Binary files /dev/null and b/docs/images/chapters/splitting/77d77c07832ad3adc3a3dec129a137bb.png differ
diff --git a/docs/images/chapters/splitting/7ad9b19d2a951c5eaf057edba3a37a5b.png b/docs/images/chapters/splitting/7ad9b19d2a951c5eaf057edba3a37a5b.png
deleted file mode 100644
index 466e9603..00000000
Binary files a/docs/images/chapters/splitting/7ad9b19d2a951c5eaf057edba3a37a5b.png and /dev/null differ
diff --git a/docs/images/chapters/whatis/4d6b98490713508b5c560e29ffa535ed.png b/docs/images/chapters/whatis/4d6b98490713508b5c560e29ffa535ed.png
new file mode 100644
index 00000000..6494d1ac
Binary files /dev/null and b/docs/images/chapters/whatis/4d6b98490713508b5c560e29ffa535ed.png differ
diff --git a/docs/images/chapters/whatis/d39b17854b29fbb3c70bec7a12820aa1.png b/docs/images/chapters/whatis/d39b17854b29fbb3c70bec7a12820aa1.png
deleted file mode 100644
index f316f4aa..00000000
Binary files a/docs/images/chapters/whatis/d39b17854b29fbb3c70bec7a12820aa1.png and /dev/null differ
diff --git a/docs/index.html b/docs/index.html
index eac83e73..1c0b0acf 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -599,12 +599,20 @@
Scripts are disabled. Showing fallback image.
-
+
+
+
And that brings us to the complicated maths: calculus.
@@ -712,8 +720,7 @@
We can range t from negative to positive infinity, and the
resulting (x,y) coordinates will always lie on a
circle with radius 1 around the origin (0,0). If we plot it for
- t from 0 to 5, we get this (use your up and down arrow keys
- to change the plot end value):
+ t from 0 to 5, we get this:
Scripts are disabled. Showing fallback image.
-
+
+
+
Bézier curves are just one out of the many classes of parametric
@@ -941,12 +956,21 @@ function Bezier(3,t):
Scripts are disabled. Showing fallback image.
-
+
+
+
+
Scripts are disabled. Showing fallback image.
-
+
+
+
+
Scripts are disabled. Showing fallback image.
-
+
+
+
@@ -1525,12 +1566,20 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
+
+
How to implement de Casteljau's algorithm
@@ -1590,38 +1639,57 @@ function RationalBezier(3,t,w[],r[]):
usually can't use the flattened for for doing true intersection
detection, or curvature alignment.
-
-
-
+
+
+
+ Scripts are disabled. Showing fallback image.
+
+
- Scripts are disabled. Showing fallback image.
-
-
-
-
+
+
+
+
+ Scripts are disabled. Showing fallback image.
+
+
- Scripts are disabled. Showing fallback image.
-
+
+
Try clicking on the sketch and using your up and down arrow keys to
@@ -1684,12 +1752,20 @@ function RationalBezier(3,t,w[],r[]):
Scripts are disabled. Showing fallback image.
-
+
+
+
implementing curve splitting
@@ -2266,12 +2342,14 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
+
@@ -2758,12 +2836,20 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
However, if you've played with that graphic a bit, you might have
@@ -2908,14 +2994,22 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
-
That looks much better!
+
That looks so much better!
For those reading along with the code: we don't even strictly
speaking need a Frenet frame to start with: we could, for instance,
diff --git a/docs/ja-JP/index.html b/docs/ja-JP/index.html
index 7a4b23d3..9158710a 100644
--- a/docs/ja-JP/index.html
+++ b/docs/ja-JP/index.html
@@ -571,12 +571,20 @@
Scripts are disabled. Showing fallback image.
-
+
+
+
@@ -2424,12 +2536,20 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
However, if you've played with that graphic a bit, you might have
@@ -2574,14 +2694,22 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
-
That looks much better!
+
That looks so much better!
For those reading along with the code: we don't even strictly
speaking need a Frenet frame to start with: we could, for instance,
diff --git a/docs/js/custom-element/api/graphics-api.js b/docs/js/custom-element/api/graphics-api.js
index 2bc5b6fd..7c3e41e9 100644
--- a/docs/js/custom-element/api/graphics-api.js
+++ b/docs/js/custom-element/api/graphics-api.js
@@ -138,6 +138,17 @@ class GraphicsAPI extends BaseAPI {
points.forEach((p) => this.movable.push(p));
}
+ setSlider(qs, handler, redraw = true) {
+ let slider = this.find(qs);
+ if (slider) {
+ slider.listen(`input`, (evt) => {
+ handler(parseFloat(evt.target.value));
+ if (redraw) this.redraw();
+ });
+ }
+ return slider;
+ }
+
/**
* Convert the canvas to an image
*/
diff --git a/docs/js/site/faster-lazy-loading.js b/docs/js/site/faster-lazy-loading.js
index e7223f7b..476bda0e 100644
--- a/docs/js/site/faster-lazy-loading.js
+++ b/docs/js/site/faster-lazy-loading.js
@@ -7,8 +7,8 @@
*/
const images = Array.from(
- document.querySelectorAll(`img[loading=lazy]`)
-).filter((img) => img.parentNode.nodeName !== `FALLBACK-IMAGE`);
+ document.querySelectorAll(`img.LaTeX.SVG[loading=lazy]`)
+);
// First, make images inert. As this happens before the document
// becomes active, this prevents images from loading anything.
@@ -41,12 +41,10 @@ function testImages() {
lock = true;
- let top = window.scrollY;
let height = document.documentElement.clientHeight;
- let bottom = top + height;
for (let pos = images.length - 1; pos >= 0; pos--) {
- test(images[pos], pos, top, bottom, height);
+ test(images[pos], pos, height);
}
if (images.length === 0) {
@@ -60,9 +58,12 @@ function testImages() {
/**
* Test individual images for whether or not they should load.
*/
-function test(img, pos, top, bottom, threshold) {
- top = Math.abs(img.offsetTop - top) < threshold;
- bottom = Math.abs(img.offsetTop + img.offsetHeight - bottom) < threshold;
+function test(img, pos, height) {
+ let top = img.getBoundingClientRect().top;
+ top = top < height;
+
+ let bottom = img.getBoundingClientRect().bottom;
+ bottom = bottom > -height;
if (top || bottom) {
img.src = img.dataset.src;
diff --git a/docs/placeholder-style.css b/docs/placeholder-style.css
index a866b96f..6a457e42 100644
--- a/docs/placeholder-style.css
+++ b/docs/placeholder-style.css
@@ -140,4 +140,8 @@ p code {
font-family: monospace;
font-size: 1.2em;
letter-spacing: -2px;
+}
+
+.slide-control {
+ width: 100%;
}
\ No newline at end of file
diff --git a/docs/zh-CN/index.html b/docs/zh-CN/index.html
index 11828102..577eb338 100644
--- a/docs/zh-CN/index.html
+++ b/docs/zh-CN/index.html
@@ -550,12 +550,20 @@
Scripts are disabled. Showing fallback image.
-
+
+
+
@@ -2434,12 +2546,20 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
However, if you've played with that graphic a bit, you might have
@@ -2584,14 +2704,22 @@ function drawCurve(points[], t):
Scripts are disabled. Showing fallback image.
-
+
+
+
-