1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-18 14:31:24 +02:00

graphics-api docs

This commit is contained in:
Pomax
2020-09-19 12:29:43 -07:00
parent 7bf5a223bf
commit 7c530fee56
31 changed files with 420 additions and 103 deletions

View File

@@ -33,7 +33,7 @@ drawSlices(w, h, a, n) {
let area = 0; let area = 0;
let step = w/n; let step = w/n;
for(let i=0, f=TAU/w, c, y; i<w; i += step) { for(let i=0, f=TAU/w, c, y; i<w; i += step) {
c = `rgba(150,150,255,${0.4 + 0.3 * random()}`; c = `rgba(150,150,255,${random(0.4, 0.7)}`;
if (n > 50) setStroke(c); if (n > 50) setStroke(c);
setFill(c); setFill(c);
y = sin((i+step/2) * f) * a; y = sin((i+step/2) * f) * a;

View File

@@ -25,7 +25,7 @@ draw() {
noStroke(); noStroke();
setFill(`rgba(100,255,100,0.4)`); setFill(`rgba(100,255,100,0.4)`);
let a = this.angle; let a = this.angle;
arc(w/2, h/2, r, a < 0 ? a : 0, a < 0 ? 0 : a, w/2, h/2); wedge(w/2, h/2, r, a < 0 ? a : 0, a < 0 ? 0 : a);
curve.drawSkeleton(); curve.drawSkeleton();
curve.drawCurve(); curve.drawCurve();

View File

@@ -26,7 +26,7 @@ draw() {
noStroke(); noStroke();
setFill(`rgba(100,255,100,0.4)`); setFill(`rgba(100,255,100,0.4)`);
let a = this.angle; let a = this.angle;
arc(w/2, h/2, r, a < 0 ? a : 0, a < 0 ? 0 : a, w/2, h/2); wedge(w/2, h/2, r, a < 0 ? a : 0, a < 0 ? 0 : a);
guess.drawSkeleton(`lightblue`); guess.drawSkeleton(`lightblue`);
guess.drawCurve(`lightblue`); guess.drawCurve(`lightblue`);

View File

@@ -53,7 +53,7 @@ computeCurvature(curve, t) {
dd = curve.dderivative(t), dd = curve.dderivative(t),
num = d.x * dd.y - d.y * dd.x, num = d.x * dd.y - d.y * dd.x,
qdsum = d.x * d.x + d.y * d.y, qdsum = d.x * d.x + d.y * d.y,
dnm = pow(qdsum, 3 / 2); dnm = qdsum ** 3/2;
if (num === 0 || dnm === 0) return 0; if (num === 0 || dnm === 0) return 0;

View File

@@ -5,8 +5,8 @@ setup() {
h = this.height; h = this.height;
for (let i=0; i<10; i++) { for (let i=0; i<10; i++) {
points.push({ points.push({
x: w/2 + random() * 20 + cos(PI*2 * i/10) * (w/2 - 40), x: w/2 + random(20) + cos(PI*2 * i/10) * (w/2 - 40),
y: h/2 + random() * 20 + sin(PI*2 * i/10) * (h/2 - 40) y: h/2 + random(20) + sin(PI*2 * i/10) * (h/2 - 40)
}); });
} }
setMovable(points); setMovable(points);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -31,7 +31,7 @@
<meta property="og:locale" content="en-GB" /> <meta property="og:locale" content="en-GB" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" /> <meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
<meta property="og:updated_time" content="2020-09-19T05:05:19+00:00" /> <meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" /> <meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" /> <meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" /> <meta property="og:tag" content="Bézier Curves" />
@@ -1649,7 +1649,7 @@ function drawCurve(points[], t):
<graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js"> <graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\reordering\71f47629388901b821976e034be159e4.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\reordering\c37918c649befad06de255a6415faf29.png" loading="lazy" />
<label>A variable-order Bézier curve</label> <label>A variable-order Bézier curve</label>
</fallback-image> </fallback-image>
<button class="raise">raise</button> <button class="raise">raise</button>
@@ -3142,21 +3142,21 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\dc74a2f2da19470b8d721ece5f3ce268.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\56533f47e73ad9fea08fa9bb3f597d49.png" loading="lazy" />
<label>A function's approximated integral</label> <label>A function's approximated integral</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24"> <graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4bffba7dda2a3556cf5b2ae7392083c6.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\5ce02cbdbc47585c588f2656d5161a32.png" loading="lazy" />
<label>A better approximation</label> <label>A better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99"> <graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4b5d220d02b08f6c9aa19389255ef8bb.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\fe2663b205d14c157a5a02bfbbd55987.png" loading="lazy" />
<label>An even better approximation</label> <label>An even better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
@@ -3389,7 +3389,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\5fcfb0572cae06717506c84768aa568c.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\7898e3a51a86afffd1a91ce0fcc99b26.png" loading="lazy" />
<label></label> </fallback-image <label></label> </fallback-image
></graphics-element> ></graphics-element>
@@ -3413,7 +3413,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\876d7b2750d7c29068ac6181c3634d25.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\78581fc4b36f2e45c704a4fce7c8368a.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" /> <input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" />
@@ -5221,7 +5221,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js"> <graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles\5801de8227960faa9bcbae578f78c2a3.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles\08ca09aacb271735e063e7e8d941a195.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
@@ -5346,7 +5346,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js"> <graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles_cubic\da768b84c91262bab8ab36f895e8569b.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles_cubic\ecacec0eb2bbe72e14b9008d854fbb06.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />

View File

@@ -33,7 +33,7 @@
<meta property="og:locale" content="ja-JP" /> <meta property="og:locale" content="ja-JP" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" /> <meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
<meta property="og:updated_time" content="2020-09-19T05:05:19+00:00" /> <meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" /> <meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" /> <meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" /> <meta property="og:tag" content="Bézier Curves" />
@@ -1485,7 +1485,7 @@ function drawCurve(points[], t):
<graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js"> <graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\reordering\71f47629388901b821976e034be159e4.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\reordering\c37918c649befad06de255a6415faf29.png" loading="lazy" />
<label>A variable-order Bézier curve</label> <label>A variable-order Bézier curve</label>
</fallback-image> </fallback-image>
<button class="raise">raise</button> <button class="raise">raise</button>
@@ -2978,21 +2978,21 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\dc74a2f2da19470b8d721ece5f3ce268.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\56533f47e73ad9fea08fa9bb3f597d49.png" loading="lazy" />
<label>A function's approximated integral</label> <label>A function's approximated integral</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24"> <graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4bffba7dda2a3556cf5b2ae7392083c6.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\5ce02cbdbc47585c588f2656d5161a32.png" loading="lazy" />
<label>A better approximation</label> <label>A better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99"> <graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4b5d220d02b08f6c9aa19389255ef8bb.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\fe2663b205d14c157a5a02bfbbd55987.png" loading="lazy" />
<label>An even better approximation</label> <label>An even better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
@@ -3225,7 +3225,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\5fcfb0572cae06717506c84768aa568c.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\7898e3a51a86afffd1a91ce0fcc99b26.png" loading="lazy" />
<label></label> </fallback-image <label></label> </fallback-image
></graphics-element> ></graphics-element>
@@ -3249,7 +3249,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\876d7b2750d7c29068ac6181c3634d25.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\78581fc4b36f2e45c704a4fce7c8368a.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" /> <input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" />
@@ -5057,7 +5057,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js"> <graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles\5801de8227960faa9bcbae578f78c2a3.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles\08ca09aacb271735e063e7e8d941a195.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
@@ -5182,7 +5182,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js"> <graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles_cubic\da768b84c91262bab8ab36f895e8569b.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles_cubic\ecacec0eb2bbe72e14b9008d854fbb06.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />

View File

@@ -0,0 +1,337 @@
# The Graphics API
Graphics code is bootstrapped and drawn uses two "master" functions:
```js
setup() {
// initialisation code goes here
}
draw() {
// drawing code goes here
}
```
All code starts at `setup()`, automatically calling `draw()` after setup has been completed. Standard JS scoping applies, so any variable declared outside of `setup`/`draw` will be a "global" variable.
## User Events
Graphics code can react to touch/mouse, which can be handled using:
- `onMouseDown()` triggered by mouse/touch start events.
- `onMouseUp()` triggered by mouse/touch end events.
- `onMouseMose()` triggered by moving the mouse/your finger.
Mouse event data can be accessed via the `this.cursor` property, which encodes:
```
{
x: current event's screen x coordinate
y: current event's screen x coordinate
down: boolean signifying whether the cursor is engaged or not
mark: {x,y} coordinate object representing where mousedown occurred
last: {x,y} coordinate object representing where the cursor was "one event ago"
diff: {x,y} coordinate object representing the x/y difference between "now" and "one event ago",
with an additional `total` propert that is an {x,y} coordinate object representing the x/y
difference between "now" and the original mousedown event.
}
```
Graphics code can also react to keyboard events, although this is a great way to make sure your code won't work for mobile devices, so it's better to use range sliders to keep things accessible. That said, they can be handled using:
- `onKeyDown()` triggered by pressing a key
- `onKeyUp()` triggered by releasing a key
Keyboard event data can be accessed via the `this.keyboard` property, which encodes:
```
{
currentKey: the name of the key associated with the current event
}
```
Additionally, the `this.keyboard` property can be consulted for named keys to see if they are currently down or not, e.g. to check whether the up arrow is down or not:
```js
draw() {
if (this.keyboard[`ArrowUp`]) {
...
}
}
```
## Controllable parameters
Graphics code can be passed external values from HTML using data attributes:
```html
<graphics-element src="..." data-propname="somevalue"></graphics-element>
```
which can be access on the code side using
```js
this.parameters.propname;
```
Additionally, graphics code has special functions for range values, either directly in code:
```js
setup() {
// name, min, max, step, initial value
addSlider(`rangeValue`, 0, 1, 0.001, 0.5);
}
draw() {
// values defined through sliders become accessible on `this`:
console.log(this.rangeValue);
}
```
Alternatively, they can be hooked into a predefined slider:
```html
<graphics-element src="..." data-propname="somevalue">
<input type="range" min="0" max="1" step="0.001" value="0.5" class="my-slider">
</graphics-element>
```
using the `setSlider` function:
```js
setup() {
// local query selector, name, initial value
setSlider(`.my-slider`, `rangeValue`, 0.5);
}
draw() {
console.log(this.rangeValue);
}
```
## Movable points
An important part of the Graphics API is showing shapes that are controlled or defined by coordinates, and as there are special functions for marking points as "movable" - that is, these points can be click/touch-dragged around a graphic. To fascilitate this, the following functions can be used:
- `setMovable(points, ...)` takes one or more arrays of points, and marks all points as "being movable", such that if the cursor activates at an x/y coordinate near one of these, that point gets assigned to `this.currentPoint`, as well as being automatically moved around as you drag the cursor around on the sketch.
- `resetMovable()` will clear the list of movable points.
- `resetMovable(points, ...)` is the same as calling `resetMovable()` followed by `setMovable(points, ...)`.
## The API
The following is the list of API functions that can be used to draw... whatever you like, really.
### gGobal constants
- `PI` 3.14159265358979
- `TAU` 6.28318530717958
- `POINTER` "default"
- `HAND` "pointer"
- `CROSS` "crosshair"
- `POLYGON` Shape.POLYGON, "Polygon"
- `CURVE` Shape.CURVE, "CatmullRom"
- `BEZIER` Shape.BEZIER, "Bezier"
- `CENTER` "center"
- `LEFT` "left"
- `RIGHT` "right"
### Instance propeties
- `this.width` the width of the graphic
- `this.height` the height of the graphic
- `this.panelWidth` the width of a single panel in the graphic, only meaningful in conjunction with `setPanelWidth` (see below)
- `this.parameters` the collection of externally passed parameters (via HTML: `data-...` attributes, via JS: a key/value object)
- `this.cursor` represents the current mouse/touch cursor state
- `this.currentPoint` whatever point thec cursor is currently close enough to to interact with
- `this.keyboard` the current keyboard state
- `this.currentShape` the currently active shape. **warning:** this value gets reset any time `start()` is used, so it is recommended to cache the current shape using `saveShape()` instead of directly referencing `this.currentShape`.
### General functions
- `setSize(width,height)` explicitly resizes the canvas. **warning:** this will reset all color, transform, etc. properties to their default values.
- `setPanelCount(int)` use this in `setup()` to let the API know that this graphic is technically a number of "separate" panels of content, setting `this.panelWidth` to `width`/`panelcount`.
- `toDataURL()` returns the graphic as PNG image, encoded as a data URL.
- `find(qs)` find an HTML elements in the `<graphics-element>` DOM tree, using a query selector
- `findAll(qs)` find all HTML elements that match the provided querySelector. **note:** unlike the DOM API, this function returns a plain array.
### Maths functions
- `abs(v)` get the absolute value
- `approx(v1, v2, epsilon = 0.001)` check whether v1 differs from v2 by no more than `epsilon`
- `atan2(dy, dx)` [atan2](https://en.wikipedia.org/wiki/Atan2)
- `binomial(n, k)` get the binomial coefficient, i.e. "n choose k"
- `ceil(v)` round any fractional number up to the next highest interger
- `constrain(v, lowest, highest)` restrict a value in its lowest and highest value.
- `cos(v)` cosine
- `dist(x1, y1, x2, y2)` the euclidean distance between (x1,y1) and (x2,y2)
- `floor(v)` round any fractional number to an integer by discarding its fractional part
- `map(v, fromStart, fromEnd, toStrart, toEnd, constrain = false)` compute a value on an interval [fromStart,fromEnd] to its corresponding value on the interval [toStart,toEnd], with optional constraining to that new interval.
- `max(...v)` find the highest number in two or more numbers
- `min(...v)` find the lowest number in two or more numbers
- `random()` generate a random value between 0 (inclusive) and 1 (exclusive)
- `random(v)` generate a random value between 0 (inclusive) and `v` (exclusive)
- `random(a,b)` generate a random value between `a` (inclusive) and `b` (exclusive)
- `round(v)` round any fractional number by applying `ceil` for any number with fractional part >= 0.5, and `floor` for any number with fractional part < 0.5.
- `sin(v)` sine
- `sqrt(v)` square root
- `tan(v)` tangent
### Property functions
- `setBorder(width = 1, color = "black")` set the canvas border width and color
- `setColor(color)` set the color for both shape stroke and fill
- `noColor()` set both stroke and fill color to "transparent"
- `setCursor(type)` set the CSS cursor type. `POINTER`, `HAND`, and `CROSS` constants are provided, other values must be supplied as string.
- `setFill(color)` set the fill color
- `noFill()` set the fill color to "transparent"
- `setFont(font)` set the text font, using [CSS font syntax](https://developer.mozilla.org/en-US/docs/Web/CSS/font)
- `setFontFamily(name)` set the font to be used, by name
- `setFontSize(px)` set the font size in pixels
- `setFontWeight(val)` set the font weight in CSS weight units
- `setGrid(size, color)` set the background grid's spacing and line coloring
- `noGrid()` do not draw a background grid
- `setLineDash(...values)` set the interval values for [dashed lines](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash)
- `noLineDash()` do not use line dashing for strokes
- `setShadow(color, px)` set the color and blur distance for drawing shape shadows
- `noShadow()` do not use shape shadows
- `setStroke(color)` set the stroke color
- `noStroke()` set the stroke color to "transparent"
- `setTextStroke(color, weight)` set the text outline stroke color and width (in pixels)
- `noTextStroke()` disable text outline
- `setWidth()` reset the stroke width to be 1 pixel wide
- `setWidth(width)` set the stroke width to a custom value, in pixels
For coloring purposes, there is also the `randomColor` function:
- `randomColor()` returns a random, full opaque CSS color
- `randomColor(opacity)` returns a random CSS color with the indicated opacity (in interval [0,1])
- `randomColor(opacity, cycle=false)` if the second parameter is explicitly set to `false`, the random seed used to generate the random color will not be updated, and the resulting random color will be the same as when the function was previously called.
For temporary work, where you might want to change some properties and then revert to the previous state, there are two functions available:
- `cacheStyle()` cache the current collection of properties. This uses a stack, with each call adding a new "snapshot" on the stack.
- `restoreStyle()` restore the most recently cached state from the stack.
### Coordinate transform function
- `rotate(angle)` rotate the coordinate system by `angle` (clockwise, in radians)
- `scale(x, y)` scale the coordinate system by a factor of `x` horizontally, and `y` vertically
- `translate(x, y)` move the coordinate system by `x` units horizontally, and `y` units vertically
- `resetTransform()` reset the coordinate system to its default values
- `transform(a,b,c,d,e,f)` transform the coordinate system by applying a transformation matrix to it. This matrix has the form:
```
| a b c |
m = | d e f |
| 0 0 1 |
```
**note:** all transforms are with respect to (0,0) irrespective of where (0,0) has been moved to through successive transforms.
In addition to transformations, there are also two functions to allow you to map screen coordinates (e.g. cursor position) to their corresponding transformed coordinate, and vice versa, to allow for drawing/computing points in either coordinate system
- `screenToWorld(x, y)` converts a screen coordinate (x,y) to its corresponding transformed coordinate system coordinate (x',y')
- `worldToScreen(x, y)` converts a transformed coordinate system coordinate (x,y) to its corresponding screen coordinate (x', y')
### Drawing functions
- `arc(x, y, r, s, e)` draw a section of outline for a circle with radius `r` centered on (x,y), starting at angle `s` and ending at angle `e`.
- `circle(x, y, r)` draw a circle at (x,y) with radius `r`
- `clear(color="white", preserveTransforms=false)` clears the graphics to a specific CSS background color, resetting the transform by default.
- `drawAxes(hlabel, hs, he, vlabel, vs, ve, w, h)` draw a set of labelled axes, using `{hlabel, hs, he}` as horizontal label, with start marker `hs` and end marker `he`, and using `{vlabel, vs, ve}` as vertical label, with start marker `vs` and end marker `ve`
- `drawGrid(division = 20)` draw a grid with the specified spacing, colored using the current stroke color
- `drawShape(...shapes)` draw one or more saved full shapes (see below)
- `image(img, x = 0, y = 0, w = auto, h = auto)` draw an image at some (x,y) coordinate, defaulting to (0,0), scaled to some width and height, defaulting to the native image dimensions
- `line(x1, y1, x2, y2)` draw a line from (x1,y1) to (x2,y2)
- `plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1)` plot a function defined by `fn` (which must take a single numerical input, and output an object of the form `{x:..., y:...}`) for inputs in the interval [start,end], at a resolution of `steps` steps, with the resulting values scaled by `xscale` horizontally, and `yscale` vertically.
- `point(x, y)` draw a single point at (x,y)
- `rect(x, y, w, h)` draw a rectangle from (x,y) with width `w` and height `h`
- `redraw()` triggers a new draw loop. Use this instead of calling `draw()` directly when you wish to draw a new frame as part of event handling.
- `text(str, x, y, alignment = LEFT)` place text, colored by the fill color, anchored to (x,y), with the type of anchoring determined by `alignemtn`. The alignment constants `LEFT`, `RIGHT`, and `CENTER` are available.
- `wedge(x, y, r, s, e)` similar to arc, but draw a full wedge
#### Shape drawing functions
- `start(type = POLYGON, factor)` set up a new `Shape` as `this.currentShape` in preparation for receiving data. Types can be `POLYGON` (default), `CURVE` (Catmull-Rom), or `BEZIER`. If `CURVE` is specified, the `factor` indicates how loose or tight the resulting Catmull-Rom curve will be.
- `segment(type, factor)` set up a new section of the shape. If left unspecified the `type` and `factor` are inherited from the current `Shape`.
- `vertex(x, y)` add a point to the current `Shape`'s current segment.
- `end(close = false)` draw the current `Shape`
- `saveShape()` returns the current shape for later reuse
## Built in object types
### Shape
The `Shape` class reprents a drawable shape consisting of one or more polygonal, Catmull-Rom curve, or Bezier curve segments. It has a minimal API:
- **`new Shape(type, factor, points = [])`** construct a new `Shape` of the specified `type` (options are `Shape.POLYGON`, `Shape.CURVE` for Catmull-Rom curves, and `Shape.BEZIER` for Bezier curves), with the specified `factor` (used for Catmull-Rom curve tightness), and optional list of points to prepopulate the first shape segment.
- `merge(other)` merge another `Shape`'s segments into this `Shape`
- `copy()` returns a copy of this `Shape`
- `newSegment(type, factor)` start a new segment in this `Shape` of the indicated type, with the indicated tightness factor.
- `vertex(p)` add an on-shape coordinate (x,y) to this `Shape`. How this vertex contributes to the overall shape drawing depends on the current segment type.
### Vector
The `Vector` class represents a 2d/3d coordinate, with a minimal standard API:
- **`new Vector(x,y,z?) / new Vector({x:,y:,z:}`** construct a new `Vector`
- `vector.dist(other, y, z = 0)` calculate the distance to some other vector-as-coordinate
- `vector.normalize(f)` return a new `Vector` representing a scaled copy of this vector, with length 1.0
- `vector.getAngle()` get the angle between this vector and the x-axis.
- `vector.reflect(other)` reflect this vector-as-coordinate over the line that some other vector lies on
- `vector.add(other)` return a new `vector` representing the addition of some other vector to this vector
- `vector.subtract(other)` return a new `vector` representing the subtraction of some other vector to this vector
- `vector.scale(f = 1)` return a new `vector` representing the scaled version of this vector
### Matrix
The `Matrix` class represents an `N`x`M` matrix, with minimal standard API:
- **`new Matrix(n,m,data?)`** construct a new `Matrix`. If `data` is provided, the matrix will be filled with that. **warning:** `data` is assumed to be `n` x `m`, but is **not** validated.
- `setData(data)` **warning:** `data` is assumed to be `n` x `m`, but is **not** validated.
- `get(i, j)` get the value at row `i` and column `j`
- `set(i, j, value)` set the value at row `i` and column `j`
- `row(i)` get the entire `i`th row as an array of values
- `col(j)` get the entire `j`th column as a (flat) array of values
- `multiply(other)` return a new `Matrix` representing the right-multiplication of this matrix with some other matrix
- `invert()` return a new `Matrix` representing the inverse of this matrix, or `undefined` if no inverse exists
- `transpose()` return a new `Matrix` representing the transpose of this matrix
...
### Bezier
The `Bezier` class is an instance of [bezier.js](https://pomax.github.io/bezierjs/) with all its API functions, extended for use on the canvas:
- static `defaultQuadratic(apiInstance)` returns a new quadratic `Bezier` with preset coordinate values tailored to the Primer on Bezier Curves. The `apiInstance` must be a reference to a valid Graphics-API instance (typically thiat will simply be `this` in your code).
- static `defaultCubic(apiInstance)` returns a new cubic `Bezier` with preset coordinate values tailored to the Primer on Bezier Curves. The `apiInstance` must be a reference to a valid Graphics-API instance (typically thiat will simply be `this` in your code).
- static `fitCurveToPoints(apiInstance, points, tvalues)` returns a new `n`-dimensional `Bezier` that has been fit to the provided list of points, constrained to the provided `tvalues`, using MSE polygonal curve fitting. The `apiInstance` must be a reference to a valid Graphics-API instance (typically thiat will simply be `this` in your code).
The extended API in addition to these static functions are:
- **`new Bezier(apiInstance, ...coords)`** construct a new `Bezier` curve controlled by three or more points, either supplied as numerical arguments, or as point objects `{x:..., y:..., z?:...}` where `z` is optional. The `apiInstance` must be a reference to a valid Graphics-API instance (typically thiat will simply be `this` in your code).
- `project(x, y)` returns an `{x:..., y:...}` object representing the projection of some point (x,y) onto this curve.
- `getPointNear(x, y, d = 5)` returns either `undefined`, or one of the `Bezier` curve's control points if the specified (x,y) coordinate is `d` or fewer pixels from a control point.
- `drawCurve(color = #333)` draws this curve on the canvas, with optional custom color
- `drawPoints(labels = true)` draws the curve's control points, with optional coordinate labels (defaulting to true)
- `drawSkeleton(color = #555)` draws this curve's coordinate polygon, with optional custom color
- `getStrutPoints(t)` get the list of points obtained through "de Casteljau" interpolation, for a given `t` value
- `drawStruts(t, color = "black", showpoints = true)` draws this curve's "de Casteljau" points and lines, for a given `t` value, with optional custom color, and optional omission of the points if only the lines are required.
- `drawBoundingBox(color = "black")` draw the axis-aligned bounding box for this `Bezier` curve with optional custom color
### BSpline
The `BSpline` class represents a generaic [B-spline](https://en.wikipedia.org/wiki/B-spline) curve, with a minimal API:
- **`new BSpline(apiInstance, points)`** constructs a B-spline controlled by a points array in which each element may be either of the form `{x: ..., y: ...}` or a numerical tuple `[x,y]`. The `apiInstance` must be a reference to a valid Graphics-API instance (typically thiat will simply be `this` in your code).
- `getLUT(count)` returns an array of `count` coordinates of the form `{x:...,y:...}`, representing a polygonal approximation of this `BSpline`.
- `formKnots(open = false)` set-and-return the list of B-spline knots using either the standard uniform interval spacing, or if `open` is set to `true`, special spacing to effect a B-spline that start and ends at the actual start and end coordinates. The knot array returned in this fashion is a live array, and updating its values **will** change the B-spline's shape.
- `formUniformKnots()` set-and-return uniformaly spaced knot values. The knot array returned in this fashion is a live array, and updating its values **will** change the B-spline's shape.
- `formWeights()` set-and-return the array of weights. These will all be uniformly initialized to 1, with the weight array returned being a live array, so that updating its values will change the B-spline's shape.

View File

@@ -38,6 +38,9 @@ class GraphicsAPI extends BaseAPI {
get HAND() { get HAND() {
return `pointer`; return `pointer`;
} }
get CROSS() {
return `crosshair`;
}
get POLYGON() { get POLYGON() {
return Shape.POLYGON; return Shape.POLYGON;
} }
@@ -56,25 +59,6 @@ class GraphicsAPI extends BaseAPI {
get RIGHT() { get RIGHT() {
return `right`; return `right`;
} }
// hatching patterns
get HATCH1() {
return this.HATCHING[0];
}
get HATCH2() {
return this.HATCHING[1];
}
get HATCH3() {
return this.HATCHING[2];
}
get HATCH4() {
return this.HATCHING[3];
}
get HATCH5() {
return this.HATCHING[4];
}
get HATCH6() {
return this.HATCHING[5];
}
onMouseDown(evt) { onMouseDown(evt) {
super.onMouseDown(evt); super.onMouseDown(evt);
@@ -205,6 +189,17 @@ class GraphicsAPI extends BaseAPI {
this.ctx.scale(x, y); this.ctx.scale(x, y);
} }
/**
* transforms: universal free transform based on applying
*
* | a b c |
* m = | d e f |
* | 0 0 1 |
*/
transform(a, b, c, d, e, f) {
this.ctx.transform(a, b, c, d, e, f);
}
/** /**
* transforms: screen to world * transforms: screen to world
*/ */
@@ -371,7 +366,7 @@ class GraphicsAPI extends BaseAPI {
/** /**
* Set the context lineWidth * Set the context lineWidth
*/ */
setWidth(width) { setWidth(width = 1) {
this.ctx.lineWidth = width; this.ctx.lineWidth = width;
} }
@@ -497,15 +492,22 @@ class GraphicsAPI extends BaseAPI {
/** /**
* Draw a circular arc * Draw a circular arc
*/ */
arc(x, y, r, s, e, cx = false, cy = false) { arc(x, y, r, s, e, wedge = false) {
this.ctx.beginPath(); this.ctx.beginPath();
if (cx !== false && cy != false) this.ctx.moveTo(cx, cy); if (wedge) this.ctx.moveTo(x, y);
this.ctx.arc(x, y, r, s, e); this.ctx.arc(x, y, r, s, e);
if (cx !== false && cy != false) this.ctx.moveTo(cx, cy); if (wedge) this.ctx.moveTo(x, y);
this.ctx.fill(); this.ctx.fill();
this.ctx.stroke(); this.ctx.stroke();
} }
/**
* Draw a circular wedge
*/
wedge(x, y, r, s, e) {
this.arc(x, y, r, s, e, true);
}
/** /**
* Draw text on the canvas * Draw text on the canvas
*/ */
@@ -540,11 +542,11 @@ class GraphicsAPI extends BaseAPI {
* Draw a function plot from [start] to [end] in [steps] steps. * Draw a function plot from [start] to [end] in [steps] steps.
* Returns the plot shape so that it can be cached for redrawing. * Returns the plot shape so that it can be cached for redrawing.
*/ */
plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1) { plot(generator, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1) {
const interval = end - start; const interval = end - start;
this.start(); this.start();
for (let i = 0, e = steps - 1, v; i < steps; i++) { for (let i = 0, e = steps - 1, v; i < steps; i++) {
v = fn(start + (interval * i) / e); v = generator(start + (interval * i) / e);
this.vertex(v.x * xscale, v.y * yscale); this.vertex(v.x * xscale, v.y * yscale);
} }
this.end(); this.end();
@@ -585,7 +587,6 @@ class GraphicsAPI extends BaseAPI {
this.currentShape.merge(shapes[i]); this.currentShape.merge(shapes[i]);
} }
this.end(); this.end();
this.STARTREPORTING = false;
} }
/** /**
@@ -601,6 +602,13 @@ class GraphicsAPI extends BaseAPI {
this.ctx.stroke(); this.ctx.stroke();
} }
/**
* Yield a snapshot of the current shape.
*/
save() {
return this.currentShape;
}
/** /**
* Polygon draw function * Polygon draw function
*/ */
@@ -645,12 +653,6 @@ class GraphicsAPI extends BaseAPI {
this.ctx.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); this.ctx.bezierCurveTo(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
} }
} }
/**
* Yield a snapshot of the current shape.
*/
save() {
return this.currentShape;
}
/** /**
* convenient grid drawing function * convenient grid drawing function
@@ -704,8 +706,15 @@ class GraphicsAPI extends BaseAPI {
return Math.round(v); return Math.round(v);
} }
random(v = 1) { random(a, b) {
return Math.random() * v; if (a === undefined) {
a = 0;
b = 1;
} else if (b === undefined) {
b = a;
a = 0;
}
return a + Math.random() * (b - a);
} }
abs(v) { abs(v) {
@@ -744,10 +753,6 @@ class GraphicsAPI extends BaseAPI {
return Math.atan2(dy, dx); return Math.atan2(dy, dx);
} }
pow(v, p) {
return Math.pow(v, p);
}
binomial(n, k) { binomial(n, k) {
return binomial(n, k); return binomial(n, k);
} }

View File

@@ -160,7 +160,7 @@ class Bezier extends Original {
return p; return p;
} }
drawBoundingBox(color) { drawBoundingBox(color = `black`) {
let bbox = this.bbox(), let bbox = this.bbox(),
mx = bbox.x.min, mx = bbox.x.min,
my = bbox.y.min, my = bbox.y.min,
@@ -169,7 +169,7 @@ class Bezier extends Original {
api = this.api; api = this.api;
api.cacheStyle(); api.cacheStyle();
api.noFill(); api.noFill();
api.setStroke(color ? color : `black`); api.setStroke(color);
api.rect(mx, my, MX - mx, MY - my); api.rect(mx, my, MX - mx, MY - my);
api.restoreStyle(); api.restoreStyle();
} }

View File

@@ -50,34 +50,9 @@ class BSpline {
return (this.knots = [...new Array(this.points.length + DEGREE + 1)].map((_, i) => i)); return (this.knots = [...new Array(this.points.length + DEGREE + 1)].map((_, i) => i));
} }
formNodes() {
const knots = this.knots;
const domain = [DEGREE, knots.length - 1 - DEGREE],
nodes = [];
for (let k = 0; k < this.points.length; k++) {
let node = 0;
for (let offset = 1; offset <= DEGREE; offset++) {
node += knots[k + offset];
}
node /= DEGREE;
if (node < knots[domain[0]]) continue;
if (node > knots[domain[1]]) continue;
nodes.push(node);
}
return (this.nodes = nodes);
}
formWeights() { formWeights() {
return (this.weights = this.points.map((p) => 1)); return (this.weights = this.points.map((p) => 1));
} }
setDegree(d) {
DEGREE += d;
this.knots = this.formKnots();
this.nodes = this.formNodes();
}
} }
export { BSpline }; export { BSpline };

View File

@@ -143,11 +143,11 @@ class Matrix {
row(i) { row(i) {
return this.data[i]; return this.data[i];
} }
col(i) { col(j) {
var d = this.data, var d = this.data,
col = []; col = [];
for (let r = 0, l = d.length; r < l; r++) { for (let r = 0, l = d.length; r < l; r++) {
col.push(d[r][i]); col.push(d[r][j]);
} }
return col; return col;
} }

View File

@@ -7,7 +7,7 @@ class Shape {
constructor(type, factor, points = []) { constructor(type, factor, points = []) {
this.first = false; this.first = false;
this.segments = []; this.segments = [];
this.addSegment(type, factor); this.newSegment(type, factor);
points.forEach((p) => this.vertex(p)); points.forEach((p) => this.vertex(p));
} }
merge(other) { merge(other) {
@@ -22,7 +22,7 @@ class Shape {
copy.segments = this.segments.map((s) => s.copy()); copy.segments = this.segments.map((s) => s.copy());
return copy; return copy;
} }
addSegment(type, factor) { newSegment(type, factor) {
this.currentSegment = new Segment(type, factor); this.currentSegment = new Segment(type, factor);
this.segments.push(this.currentSegment); this.segments.push(this.currentSegment);
} }

View File

@@ -27,7 +27,7 @@
<meta property="og:locale" content="en-GB" /> <meta property="og:locale" content="en-GB" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:published_time" content="2020-09-20T12:00:00+00:00" /> <meta property="og:published_time" content="2020-09-20T12:00:00+00:00" />
<meta property="og:updated_time" content="2020-09-19T05:05:19+00:00" /> <meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" /> <meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" /> <meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" /> <meta property="og:tag" content="Bézier Curves" />

View File

@@ -33,7 +33,7 @@
<meta property="og:locale" content="zh-CN" /> <meta property="og:locale" content="zh-CN" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" /> <meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
<meta property="og:updated_time" content="2020-09-19T05:05:19+00:00" /> <meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" /> <meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" /> <meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" /> <meta property="og:tag" content="Bézier Curves" />
@@ -1457,7 +1457,7 @@ function drawCurve(points[], t):
<graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js"> <graphics-element title="A variable-order Bézier curve" width="275" height="275" src="./chapters/reordering/reorder.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\reordering\71f47629388901b821976e034be159e4.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\reordering\c37918c649befad06de255a6415faf29.png" loading="lazy" />
<label>A variable-order Bézier curve</label> <label>A variable-order Bézier curve</label>
</fallback-image> </fallback-image>
<button class="raise">raise</button> <button class="raise">raise</button>
@@ -2950,21 +2950,21 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\dc74a2f2da19470b8d721ece5f3ce268.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\56533f47e73ad9fea08fa9bb3f597d49.png" loading="lazy" />
<label>A function's approximated integral</label> <label>A function's approximated integral</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24"> <graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4bffba7dda2a3556cf5b2ae7392083c6.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\5ce02cbdbc47585c588f2656d5161a32.png" loading="lazy" />
<label>A better approximation</label> <label>A better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99"> <graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\arclength\4b5d220d02b08f6c9aa19389255ef8bb.png" loading="lazy" /> <img width="275px" height="275px" src="images\chapters\arclength\fe2663b205d14c157a5a02bfbbd55987.png" loading="lazy" />
<label>An even better approximation</label> <label>An even better approximation</label>
</fallback-image></graphics-element </fallback-image></graphics-element
> >
@@ -3197,7 +3197,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\5fcfb0572cae06717506c84768aa568c.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\7898e3a51a86afffd1a91ce0fcc99b26.png" loading="lazy" />
<label></label> </fallback-image <label></label> </fallback-image
></graphics-element> ></graphics-element>
@@ -3221,7 +3221,7 @@ y = curve.get(t).y</code></pre>
> >
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\curvature\876d7b2750d7c29068ac6181c3634d25.png" loading="lazy" /> <img width="825px" height="275px" src="images\chapters\curvature\78581fc4b36f2e45c704a4fce7c8368a.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" /> <input type="range" min="0" max="2" step="0.0005" value="0" class="slide-control" />
@@ -5029,7 +5029,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js"> <graphics-element title="Quadratic Bézier arc approximation" width="400" height="400" src="./chapters/circles/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles\5801de8227960faa9bcbae578f78c2a3.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles\08ca09aacb271735e063e7e8d941a195.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
@@ -5154,7 +5154,7 @@ for p = 1 to points.length-3 (inclusive):
<graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js"> <graphics-element title="Cubic Bézier arc approximation" width="400" height="400" src="./chapters/circles_cubic/arc-approximation.js">
<fallback-image> <fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span> <span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="400px" height="400px" src="images\chapters\circles_cubic\da768b84c91262bab8ab36f895e8569b.png" loading="lazy" /> <img width="400px" height="400px" src="images\chapters\circles_cubic\ecacec0eb2bbe72e14b9008d854fbb06.png" loading="lazy" />
<label></label> <label></label>
</fallback-image> </fallback-image>
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" /> <input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />