graphics-api docs
@@ -33,7 +33,7 @@ drawSlices(w, h, a, n) {
|
||||
let area = 0;
|
||||
let step = w/n;
|
||||
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);
|
||||
setFill(c);
|
||||
y = sin((i+step/2) * f) * a;
|
||||
|
@@ -25,7 +25,7 @@ draw() {
|
||||
noStroke();
|
||||
setFill(`rgba(100,255,100,0.4)`);
|
||||
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.drawCurve();
|
||||
|
@@ -26,7 +26,7 @@ draw() {
|
||||
noStroke();
|
||||
setFill(`rgba(100,255,100,0.4)`);
|
||||
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.drawCurve(`lightblue`);
|
||||
|
@@ -53,7 +53,7 @@ computeCurvature(curve, t) {
|
||||
dd = curve.dderivative(t),
|
||||
num = d.x * dd.y - d.y * dd.x,
|
||||
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;
|
||||
|
||||
|
@@ -5,8 +5,8 @@ setup() {
|
||||
h = this.height;
|
||||
for (let i=0; i<10; i++) {
|
||||
points.push({
|
||||
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)
|
||||
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)
|
||||
});
|
||||
}
|
||||
setMovable(points);
|
||||
|
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
@@ -31,7 +31,7 @@
|
||||
<meta property="og:locale" content="en-GB" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||
<meta property="og:updated_time" content="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:section" 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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<button class="raise">raise</button>
|
||||
@@ -3142,21 +3142,21 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
@@ -3389,7 +3389,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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
|
||||
></graphics-element>
|
||||
|
||||
@@ -3413,7 +3413,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
|
||||
|
@@ -33,7 +33,7 @@
|
||||
<meta property="og:locale" content="ja-JP" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||
<meta property="og:updated_time" content="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:section" 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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<button class="raise">raise</button>
|
||||
@@ -2978,21 +2978,21 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
@@ -3225,7 +3225,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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
|
||||
></graphics-element>
|
||||
|
||||
@@ -3249,7 +3249,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
|
||||
|
337
docs/js/custom-element/api/README.md
Normal 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.
|
@@ -38,6 +38,9 @@ class GraphicsAPI extends BaseAPI {
|
||||
get HAND() {
|
||||
return `pointer`;
|
||||
}
|
||||
get CROSS() {
|
||||
return `crosshair`;
|
||||
}
|
||||
get POLYGON() {
|
||||
return Shape.POLYGON;
|
||||
}
|
||||
@@ -56,25 +59,6 @@ class GraphicsAPI extends BaseAPI {
|
||||
get 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) {
|
||||
super.onMouseDown(evt);
|
||||
@@ -205,6 +189,17 @@ class GraphicsAPI extends BaseAPI {
|
||||
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
|
||||
*/
|
||||
@@ -371,7 +366,7 @@ class GraphicsAPI extends BaseAPI {
|
||||
/**
|
||||
* Set the context lineWidth
|
||||
*/
|
||||
setWidth(width) {
|
||||
setWidth(width = 1) {
|
||||
this.ctx.lineWidth = width;
|
||||
}
|
||||
|
||||
@@ -497,15 +492,22 @@ class GraphicsAPI extends BaseAPI {
|
||||
/**
|
||||
* 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();
|
||||
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);
|
||||
if (cx !== false && cy != false) this.ctx.moveTo(cx, cy);
|
||||
if (wedge) this.ctx.moveTo(x, y);
|
||||
this.ctx.fill();
|
||||
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
|
||||
*/
|
||||
@@ -540,11 +542,11 @@ class GraphicsAPI extends BaseAPI {
|
||||
* Draw a function plot from [start] to [end] in [steps] steps.
|
||||
* 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;
|
||||
this.start();
|
||||
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.end();
|
||||
@@ -585,7 +587,6 @@ class GraphicsAPI extends BaseAPI {
|
||||
this.currentShape.merge(shapes[i]);
|
||||
}
|
||||
this.end();
|
||||
this.STARTREPORTING = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -601,6 +602,13 @@ class GraphicsAPI extends BaseAPI {
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
/**
|
||||
* Yield a snapshot of the current shape.
|
||||
*/
|
||||
save() {
|
||||
return this.currentShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Yield a snapshot of the current shape.
|
||||
*/
|
||||
save() {
|
||||
return this.currentShape;
|
||||
}
|
||||
|
||||
/**
|
||||
* convenient grid drawing function
|
||||
@@ -704,8 +706,15 @@ class GraphicsAPI extends BaseAPI {
|
||||
return Math.round(v);
|
||||
}
|
||||
|
||||
random(v = 1) {
|
||||
return Math.random() * v;
|
||||
random(a, b) {
|
||||
if (a === undefined) {
|
||||
a = 0;
|
||||
b = 1;
|
||||
} else if (b === undefined) {
|
||||
b = a;
|
||||
a = 0;
|
||||
}
|
||||
return a + Math.random() * (b - a);
|
||||
}
|
||||
|
||||
abs(v) {
|
||||
@@ -744,10 +753,6 @@ class GraphicsAPI extends BaseAPI {
|
||||
return Math.atan2(dy, dx);
|
||||
}
|
||||
|
||||
pow(v, p) {
|
||||
return Math.pow(v, p);
|
||||
}
|
||||
|
||||
binomial(n, k) {
|
||||
return binomial(n, k);
|
||||
}
|
||||
|
@@ -160,7 +160,7 @@ class Bezier extends Original {
|
||||
return p;
|
||||
}
|
||||
|
||||
drawBoundingBox(color) {
|
||||
drawBoundingBox(color = `black`) {
|
||||
let bbox = this.bbox(),
|
||||
mx = bbox.x.min,
|
||||
my = bbox.y.min,
|
||||
@@ -169,7 +169,7 @@ class Bezier extends Original {
|
||||
api = this.api;
|
||||
api.cacheStyle();
|
||||
api.noFill();
|
||||
api.setStroke(color ? color : `black`);
|
||||
api.setStroke(color);
|
||||
api.rect(mx, my, MX - mx, MY - my);
|
||||
api.restoreStyle();
|
||||
}
|
||||
|
@@ -50,34 +50,9 @@ class BSpline {
|
||||
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() {
|
||||
return (this.weights = this.points.map((p) => 1));
|
||||
}
|
||||
|
||||
setDegree(d) {
|
||||
DEGREE += d;
|
||||
this.knots = this.formKnots();
|
||||
this.nodes = this.formNodes();
|
||||
}
|
||||
}
|
||||
|
||||
export { BSpline };
|
||||
|
@@ -143,11 +143,11 @@ class Matrix {
|
||||
row(i) {
|
||||
return this.data[i];
|
||||
}
|
||||
col(i) {
|
||||
col(j) {
|
||||
var d = this.data,
|
||||
col = [];
|
||||
for (let r = 0, l = d.length; r < l; r++) {
|
||||
col.push(d[r][i]);
|
||||
col.push(d[r][j]);
|
||||
}
|
||||
return col;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ class Shape {
|
||||
constructor(type, factor, points = []) {
|
||||
this.first = false;
|
||||
this.segments = [];
|
||||
this.addSegment(type, factor);
|
||||
this.newSegment(type, factor);
|
||||
points.forEach((p) => this.vertex(p));
|
||||
}
|
||||
merge(other) {
|
||||
@@ -22,7 +22,7 @@ class Shape {
|
||||
copy.segments = this.segments.map((s) => s.copy());
|
||||
return copy;
|
||||
}
|
||||
addSegment(type, factor) {
|
||||
newSegment(type, factor) {
|
||||
this.currentSegment = new Segment(type, factor);
|
||||
this.segments.push(this.currentSegment);
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@
|
||||
<meta property="og:locale" content="en-GB" />
|
||||
<meta property="og:type" content="article" />
|
||||
<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:section" content="Bézier Curves" />
|
||||
<meta property="og:tag" content="Bézier Curves" />
|
||||
|
@@ -33,7 +33,7 @@
|
||||
<meta property="og:locale" content="zh-CN" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||
<meta property="og:updated_time" content="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:section" 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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<button class="raise">raise</button>
|
||||
@@ -2950,21 +2950,21 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="A better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="24">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
<graphics-element title="An even better approximation" width="275" height="275" src="./chapters/arclength/draw-slices.js" data-steps="99">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image></graphics-element
|
||||
>
|
||||
@@ -3197,7 +3197,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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
|
||||
></graphics-element>
|
||||
|
||||
@@ -3221,7 +3221,7 @@ y = curve.get(t).y</code></pre>
|
||||
>
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<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">
|
||||
<fallback-image>
|
||||
<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>
|
||||
</fallback-image>
|
||||
<input type="range" min="-3.1415" max="3.1415" step="0.01" value="-0.7854" class="slide-control" />
|
||||
|