@altpsyche/maths 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -360,6 +360,31 @@ marks onto a two-dimensional canvas, which is what a recording needs, because an
360
360
  one surface. A test holds the two to emitting the same geometry and the same style for every
361
361
  mark.
362
362
 
363
+ ## Frames out
364
+
365
+ `framesOf(figure, options)` walks a figure at a fixed step and hands back a frame at a time. A frame
366
+ is its index, its time, its marks and the view those marks are painted through, read together at one
367
+ moment. A consumer that asks for the marks and the view in two calls has two chances to pass different
368
+ times, and a figure whose view moves then paints its marks through the matrix of some other moment:
369
+ the flat demo's view is carried 312 across its own walk, in the units a 1080 by 600 surface counts in.
370
+
371
+ Frames come back one at a time rather than as a list. Ten seconds at sixty frames a second is six
372
+ hundred frames of every mark a figure draws, and a recorder encodes a frame and throws it away.
373
+ `frameTimes` answers the times up front, since a recorder showing a reader how far along it is needs
374
+ the total before it has drawn anything.
375
+
376
+ The step is given as a rate or as a count, and the two are different questions. A recorder knows how
377
+ fast the frames play and needs a step of exactly one over that, or the encoded video drifts from the
378
+ figure's own clock. A strip knows how many pictures fit across a page and wants them spread over the
379
+ whole figure. A walk stops strictly before the duration either way: the frame at the duration of a
380
+ figure that loops is its own first frame, and a recording would show it twice. The rotation strip
381
+ above is a walk of four frames over a six second turn, and it draws the same bytes as the four times
382
+ that were written out by hand before it.
383
+
384
+ Nothing here writes a file. Every frame of both demos is painted through `paintCanvas` and written by
385
+ `svgMarkup` in the suite, which is the whole claim and needs no browser, and what a consumer does with
386
+ a painted frame is the consumer's own.
387
+
363
388
  ## The way in
364
389
 
365
390
  `pathFromData` reads an SVG `d` attribute as a path, which is the inverse of what the SVG painter
@@ -0,0 +1,57 @@
1
+ /**
2
+ * A figure walked at a fixed step, a frame at a time.
3
+ *
4
+ * A frame is the marks and the view read at one time, handed over together. A
5
+ * consumer that asked for them separately holds two calls it can pass different
6
+ * times, and a figure whose view moves then paints its marks through the matrix
7
+ * of some other moment.
8
+ *
9
+ * Frames come back one at a time rather than as a list. A ten second figure at
10
+ * sixty frames a second is six hundred frames of every mark it draws, and a
11
+ * recorder encodes a frame and throws it away.
12
+ */
13
+ import { type Figure } from './figure.js';
14
+ import type { Mark } from './mark.js';
15
+ import type { Mat3 } from '../values/mat3.js';
16
+ export interface Frame {
17
+ /** Its place in the walk, counting from nothing. */
18
+ index: number;
19
+ /** The time it was read at, in seconds. */
20
+ seconds: number;
21
+ marks: readonly Mark[];
22
+ /** The matrix a painter needs for these marks, built at this frame's own
23
+ * time. */
24
+ view: Mat3;
25
+ }
26
+ /**
27
+ * How the walk is stepped, as a rate or as a count.
28
+ *
29
+ * The two are different questions. A recorder knows how fast the frames play and
30
+ * needs a step of exactly one over that, or the encoded video drifts from the
31
+ * figure's own clock. A strip knows how many pictures fit across a page and wants
32
+ * them spread over the whole figure.
33
+ */
34
+ export type FrameStep = {
35
+ fps: number;
36
+ frames?: never;
37
+ } | {
38
+ frames: number;
39
+ fps?: never;
40
+ };
41
+ export type FramesOptions = FrameStep & {
42
+ /** The surface the view is built for, in whatever units a painter counts in. */
43
+ width: number;
44
+ height: number;
45
+ };
46
+ /**
47
+ * The times a walk reads, which a recorder needs before it has drawn anything to
48
+ * say how far along it is.
49
+ *
50
+ * A walk stops strictly before the duration. The frame at the duration of a
51
+ * figure that loops is its own first frame, and a recording would show it twice.
52
+ * A figure with no duration is one frame, since a picture that never moves still
53
+ * has a picture.
54
+ */
55
+ export declare function frameTimes(figure: Figure, step: FrameStep): number[];
56
+ /** A figure walked at a fixed step, a frame at a time. */
57
+ export declare function framesOf(figure: Figure, options: FramesOptions): Generator<Frame>;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A figure walked at a fixed step, a frame at a time.
3
+ *
4
+ * A frame is the marks and the view read at one time, handed over together. A
5
+ * consumer that asked for them separately holds two calls it can pass different
6
+ * times, and a figure whose view moves then paints its marks through the matrix
7
+ * of some other moment.
8
+ *
9
+ * Frames come back one at a time rather than as a list. A ten second figure at
10
+ * sixty frames a second is six hundred frames of every mark it draws, and a
11
+ * recorder encodes a frame and throws it away.
12
+ */
13
+ import { at, durationOf, viewAt } from './figure.js';
14
+ /**
15
+ * The times a walk reads, which a recorder needs before it has drawn anything to
16
+ * say how far along it is.
17
+ *
18
+ * A walk stops strictly before the duration. The frame at the duration of a
19
+ * figure that loops is its own first frame, and a recording would show it twice.
20
+ * A figure with no duration is one frame, since a picture that never moves still
21
+ * has a picture.
22
+ */
23
+ export function frameTimes(figure, step) {
24
+ const duration = durationOf(figure);
25
+ const count = step.fps === undefined
26
+ ? Math.max(1, Math.round(step.frames))
27
+ : Math.max(1, Math.round(duration * step.fps));
28
+ const gap = step.fps === undefined ? duration / count : 1 / step.fps;
29
+ return Array.from({ length: count }, (_, index) => index * gap);
30
+ }
31
+ /** A figure walked at a fixed step, a frame at a time. */
32
+ export function* framesOf(figure, options) {
33
+ const times = frameTimes(figure, options);
34
+ for (let index = 0; index < times.length; index += 1) {
35
+ const seconds = times[index];
36
+ yield {
37
+ index,
38
+ seconds,
39
+ marks: at(figure, seconds),
40
+ view: viewAt(figure, seconds, options.width, options.height),
41
+ };
42
+ }
43
+ }
package/dist/index.d.ts CHANGED
@@ -70,6 +70,8 @@ export { lengthOf, pointAlong } from './figure/length.js';
70
70
  export { trimPath } from './figure/trim.js';
71
71
  export { alignPaths, lerpPath } from './figure/morph.js';
72
72
  export { at, durationOf, loops, sameMarks, viewAt } from './figure/figure.js';
73
+ export { frameTimes, framesOf } from './figure/frames.js';
74
+ export type { Frame, FrameStep, FramesOptions } from './figure/frames.js';
73
75
  export type { Figure, Values } from './figure/figure.js';
74
76
  export { pathData, paintSvg, svgElements, svgMarkup } from './paint/svg.js';
75
77
  export type { ElementMaker, PaintNode, PaintTarget, SvgElement } from './paint/svg.js';
package/dist/index.js CHANGED
@@ -42,6 +42,7 @@ export { lengthOf, pointAlong } from './figure/length.js';
42
42
  export { trimPath } from './figure/trim.js';
43
43
  export { alignPaths, lerpPath } from './figure/morph.js';
44
44
  export { at, durationOf, loops, sameMarks, viewAt } from './figure/figure.js';
45
+ export { frameTimes, framesOf } from './figure/frames.js';
45
46
  export { pathData, paintSvg, svgElements, svgMarkup } from './paint/svg.js';
46
47
  export { paintCanvas } from './paint/canvas.js';
47
48
  export { arrow, brace, bracePath, callout, dot } from './figure/annotate.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altpsyche/maths",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "The mathematics AltPsyche's figures are drawn from: vectors, matrices, curves, and a value walked over time.",
5
5
  "license": "MIT",
6
6
  "author": "Siva",