@thi.ng/viz 0.7.18 → 0.8.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2025-07-10T14:20:23Z
3
+ - **Last updated**: 2025-07-17T15:09:00Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -11,6 +11,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
11
11
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
12
12
  and/or version bumps of transitive dependencies.
13
13
 
14
+ ## [0.8.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/viz@0.8.0) (2025-07-17)
15
+
16
+ #### 🚀 Features
17
+
18
+ - add vectorField() plot fn & helpers ([3d2263c](https://github.com/thi-ng/umbrella/commit/3d2263c))
19
+
14
20
  ## [0.7.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/viz@0.7.0) (2025-02-24)
15
21
 
16
22
  #### 🚀 Features
package/README.md CHANGED
@@ -97,7 +97,7 @@ For Node.js REPL:
97
97
  const viz = await import("@thi.ng/viz");
98
98
  ```
99
99
 
100
- Package sizes (brotli'd, pre-treeshake): ESM: 2.63 KB
100
+ Package sizes (brotli'd, pre-treeshake): ESM: 2.99 KB
101
101
 
102
102
  ## Dependencies
103
103
 
@@ -108,6 +108,7 @@ Package sizes (brotli'd, pre-treeshake): ESM: 2.63 KB
108
108
  - [@thi.ng/object-utils](https://github.com/thi-ng/umbrella/tree/develop/packages/object-utils)
109
109
  - [@thi.ng/strings](https://github.com/thi-ng/umbrella/tree/develop/packages/strings)
110
110
  - [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
111
+ - [@thi.ng/vectors](https://github.com/thi-ng/umbrella/tree/develop/packages/vectors)
111
112
 
112
113
  Note: @thi.ng/api is in _most_ cases a type-only import (not used at runtime)
113
114
 
package/index.d.ts CHANGED
@@ -11,4 +11,5 @@ export * from "./plot/line.js";
11
11
  export * from "./plot/scatter.js";
12
12
  export * from "./plot/stacked-intervals.js";
13
13
  export * from "./plot/utils.js";
14
+ export * from "./plot/vector-field.js";
14
15
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -11,3 +11,4 @@ export * from "./plot/line.js";
11
11
  export * from "./plot/scatter.js";
12
12
  export * from "./plot/stacked-intervals.js";
13
13
  export * from "./plot/utils.js";
14
+ export * from "./plot/vector-field.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/viz",
3
- "version": "0.7.18",
3
+ "version": "0.8.0",
4
4
  "description": "Declarative, functional & multi-format data visualization toolkit based around @thi.ng/hiccup",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -46,12 +46,13 @@
46
46
  },
47
47
  "dependencies": {
48
48
  "@thi.ng/api": "^8.11.30",
49
- "@thi.ng/arrays": "^2.13.2",
49
+ "@thi.ng/arrays": "^2.13.3",
50
50
  "@thi.ng/checks": "^3.7.10",
51
51
  "@thi.ng/math": "^5.11.30",
52
52
  "@thi.ng/object-utils": "^1.2.2",
53
53
  "@thi.ng/strings": "^3.9.16",
54
- "@thi.ng/transducers": "^9.6.0"
54
+ "@thi.ng/transducers": "^9.6.1",
55
+ "@thi.ng/vectors": "^8.3.3"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@thi.ng/date": "^2.7.56",
@@ -136,6 +137,9 @@
136
137
  "./plot/utils": {
137
138
  "default": "./plot/utils.js"
138
139
  },
140
+ "./plot/vector-field": {
141
+ "default": "./plot/vector-field.js"
142
+ },
139
143
  "./plot": {
140
144
  "default": "./plot.js"
141
145
  }
@@ -149,5 +153,5 @@
149
153
  "status": "alpha",
150
154
  "year": 2014
151
155
  },
152
- "gitHead": "a81765bd79046980463c56a8bd187f9aaa88dd65\n"
156
+ "gitHead": "4e98c38a817045d0e9a5b8bb6da23c00a721c3e0\n"
153
157
  }
@@ -0,0 +1,57 @@
1
+ import { type ReadonlyVec } from "@thi.ng/vectors";
2
+ import type { PlotFn } from "../api.js";
3
+ export interface VectorFieldOpts {
4
+ /**
5
+ * Group attributes.
6
+ */
7
+ attribs?: any;
8
+ /**
9
+ * Offset vector (in domain/grid coords), used to compute projected screen
10
+ * coords.
11
+ *
12
+ * @defaultValue [0.5, 0.5]
13
+ */
14
+ offset: ReadonlyVec;
15
+ /**
16
+ * Vector scale factor (applied to original field vectors)
17
+ *
18
+ * @defaultValue 1
19
+ */
20
+ scale: number;
21
+ /**
22
+ * Shape definition for visualizing individual vectors. Uses
23
+ * {@link vectorShapeLine} by default.
24
+ */
25
+ shape: VectorFieldShape;
26
+ }
27
+ export interface VectorFieldShape {
28
+ /**
29
+ * Optional marker for easy vector arrow visualization & reuse by shape function.
30
+ */
31
+ marker?: any[];
32
+ /**
33
+ * Shape function to represent a vector in the diagram as thi.ng/hiccup
34
+ * compatible shape/element.
35
+ *
36
+ * @param a - vector start point (in screen coords)
37
+ * @param b - vector end point (in screen coords)
38
+ * @param v - original vector
39
+ */
40
+ fn: (a: ReadonlyVec, b: ReadonlyVec, v: ReadonlyVec) => any;
41
+ }
42
+ /**
43
+ * Vectorfield plot function.
44
+ *
45
+ * @remarks
46
+ * IMPORTANT: Domain ranges for this plot function MUST be zero-based and
47
+ * integer-sized, corresponding to the shape of the supplied field data. The
48
+ * field vectors should be normalized, but don't have to be...
49
+ *
50
+ * @param data
51
+ * @param opts
52
+ */
53
+ export declare const vectorField: (data: ReadonlyVec[][], opts?: Partial<VectorFieldOpts>) => PlotFn;
54
+ export declare const vectorShapeLine: (size?: number) => VectorFieldShape;
55
+ export declare const vectorShapeLineHSL: (size?: number) => VectorFieldShape;
56
+ export declare const vectorShapeDial: VectorFieldShape;
57
+ //# sourceMappingURL=vector-field.d.ts.map
@@ -0,0 +1,71 @@
1
+ import { mapcatIndexed } from "@thi.ng/transducers";
2
+ import { dist2, heading } from "@thi.ng/vectors";
3
+ import { __valueMapper } from "./utils.js";
4
+ const vectorField = (data, opts = {}) => (spec) => {
5
+ const scale = opts.scale ?? 1;
6
+ const [ox, oy] = opts.offset ?? [0.5, 0.5];
7
+ const { marker, fn } = opts.shape ?? vectorShapeLine();
8
+ const mapper = __valueMapper(spec.xaxis, spec.yaxis, spec.project);
9
+ return [
10
+ "g",
11
+ opts.attribs || {},
12
+ marker,
13
+ ...mapcatIndexed(
14
+ (y, row) => row.map(
15
+ (v, x) => fn(
16
+ mapper([x + ox, y + oy]),
17
+ mapper([
18
+ x + ox + v[0] * scale,
19
+ y + oy + v[1] * scale
20
+ ]),
21
+ v
22
+ )
23
+ ),
24
+ data
25
+ )
26
+ ];
27
+ };
28
+ const vectorShapeLine = (size = 5) => ({
29
+ marker: [
30
+ "marker",
31
+ {
32
+ id: "arrow",
33
+ viewBox: "0 0 10 10",
34
+ refX: 9,
35
+ refY: 5,
36
+ markerWidth: size,
37
+ markerHeight: size,
38
+ orient: "auto-start-reverse"
39
+ },
40
+ [
41
+ "path",
42
+ {
43
+ stroke: "none",
44
+ fill: "context-fill",
45
+ d: "M0,0L10,5L0,10z"
46
+ }
47
+ ]
48
+ ],
49
+ fn: (a, b) => ["line", { "marker-end": "url(#arrow)" }, a, b]
50
+ });
51
+ const vectorShapeLineHSL = (size = 5) => ({
52
+ ...vectorShapeLine(size),
53
+ fn: (a, b, v) => {
54
+ const col = `hsl(${heading(v).toFixed(2)}rad,100%,50%)`;
55
+ return [
56
+ "line",
57
+ { "marker-end": "url(#arrow)", fill: col, stroke: col },
58
+ a,
59
+ b
60
+ ];
61
+ }
62
+ });
63
+ const vectorShapeDial = {
64
+ fn: (a, b) => ["g", {}, ["circle", {}, a, dist2(a, b)], ["line", {}, a, b]]
65
+ };
66
+ export {
67
+ vectorField,
68
+ vectorShapeDial,
69
+ vectorShapeLine,
70
+ vectorShapeLineHSL
71
+ };