@johnhenry/math-sample 0.0.0-stage → 0.1.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.
Files changed (62) hide show
  1. package/README.md +244 -2
  2. package/dist/budget.d.ts +47 -0
  3. package/dist/budget.d.ts.map +1 -0
  4. package/dist/budget.js +44 -0
  5. package/dist/budget.js.map +1 -0
  6. package/dist/complex.d.ts +79 -0
  7. package/dist/complex.d.ts.map +1 -0
  8. package/dist/complex.js +236 -0
  9. package/dist/complex.js.map +1 -0
  10. package/dist/expr.d.ts +38 -0
  11. package/dist/expr.d.ts.map +1 -0
  12. package/dist/expr.js +264 -0
  13. package/dist/expr.js.map +1 -0
  14. package/dist/field2d.d.ts +58 -0
  15. package/dist/field2d.d.ts.map +1 -0
  16. package/dist/field2d.js +199 -0
  17. package/dist/field2d.js.map +1 -0
  18. package/dist/index.d.ts +11 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +10 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/mesh.d.ts +90 -0
  23. package/dist/mesh.d.ts.map +1 -0
  24. package/dist/mesh.js +294 -0
  25. package/dist/mesh.js.map +1 -0
  26. package/dist/ode.d.ts +147 -0
  27. package/dist/ode.d.ts.map +1 -0
  28. package/dist/ode.js +466 -0
  29. package/dist/ode.js.map +1 -0
  30. package/dist/sample.d.ts +114 -0
  31. package/dist/sample.d.ts.map +1 -0
  32. package/dist/sample.js +308 -0
  33. package/dist/sample.js.map +1 -0
  34. package/dist/series.d.ts +53 -0
  35. package/dist/series.d.ts.map +1 -0
  36. package/dist/series.js +158 -0
  37. package/dist/series.js.map +1 -0
  38. package/dist/svg.d.ts +37 -0
  39. package/dist/svg.d.ts.map +1 -0
  40. package/dist/svg.js +82 -0
  41. package/dist/svg.js.map +1 -0
  42. package/dist/ticks.d.ts +17 -0
  43. package/dist/ticks.d.ts.map +1 -0
  44. package/dist/ticks.js +47 -0
  45. package/dist/ticks.js.map +1 -0
  46. package/dist/viewport.d.ts +59 -0
  47. package/dist/viewport.d.ts.map +1 -0
  48. package/dist/viewport.js +111 -0
  49. package/dist/viewport.js.map +1 -0
  50. package/package.json +70 -4
  51. package/src/budget.ts +72 -0
  52. package/src/complex.ts +327 -0
  53. package/src/expr.ts +283 -0
  54. package/src/field2d.ts +259 -0
  55. package/src/index.ts +112 -0
  56. package/src/mesh.ts +376 -0
  57. package/src/ode.ts +633 -0
  58. package/src/sample.ts +391 -0
  59. package/src/series.ts +209 -0
  60. package/src/svg.ts +124 -0
  61. package/src/ticks.ts +46 -0
  62. package/src/viewport.ts +150 -0
@@ -0,0 +1,199 @@
1
+ import { assertCount, assertRange, Meter, progress } from "./budget.js";
2
+ function dims(g) {
3
+ const [nx, ny] = typeof g === "number" ? [g, g] : (g ?? [128, 128]);
4
+ assertCount("grid", nx, 1);
5
+ assertCount("grid", ny, 1);
6
+ return [nx, ny];
7
+ }
8
+ function marching(f, xDomain, yDomain, levels, options) {
9
+ const [nx, ny] = dims(options.grid);
10
+ assertRange("x domain", xDomain);
11
+ assertRange("y domain", yDomain);
12
+ const meter = new Meter(options, options);
13
+ const hx = (xDomain.max - xDomain.min) / nx;
14
+ const hy = (yDomain.max - yDomain.min) / ny;
15
+ const segs = levels.map(() => []);
16
+ let prev = new Float64Array(nx + 1);
17
+ let cur = new Float64Array(nx + 1);
18
+ const row = (j, out) => {
19
+ const y = yDomain.min + j * hy;
20
+ for (let i = 0; i <= nx; i++)
21
+ out[i] = f(xDomain.min + i * hx, y);
22
+ };
23
+ let reason;
24
+ row(0, prev);
25
+ meter.spend(nx + 1);
26
+ let done = 0;
27
+ for (let j = 0; j < ny; j++) {
28
+ reason = meter.check(nx + 1);
29
+ if (reason)
30
+ break;
31
+ row(j + 1, cur);
32
+ meter.spend(nx + 1);
33
+ const y0 = yDomain.min + j * hy;
34
+ for (let i = 0; i < nx; i++) {
35
+ const x0 = xDomain.min + i * hx;
36
+ const v = [prev[i], prev[i + 1], cur[i + 1], cur[i]]; // corners ccw from bottom-left
37
+ if (!v.every(Number.isFinite))
38
+ continue; // holes: no segments through undefined cells
39
+ const cx = [x0, x0 + hx, x0 + hx, x0];
40
+ const cy = [y0, y0, y0 + hy, y0 + hy];
41
+ levels.forEach((level, li) => {
42
+ const s = v.map((q) => q - level);
43
+ // edge e joins corner e and corner e+1
44
+ const cross = (e) => {
45
+ const a = s[e];
46
+ const b = s[(e + 1) % 4];
47
+ if (a < 0 === b < 0)
48
+ return undefined; // a === 0 counts as >= 0 on the positive side
49
+ const t = a / (a - b);
50
+ const ea = e;
51
+ const eb = (e + 1) % 4;
52
+ return [
53
+ cx[ea] + t * (cx[eb] - cx[ea]),
54
+ cy[ea] + t * (cy[eb] - cy[ea]),
55
+ ];
56
+ };
57
+ const pts = [0, 1, 2, 3].map(cross);
58
+ const idx = [0, 1, 2, 3].filter((e) => pts[e]);
59
+ const out = segs[li];
60
+ const emit = (p, q) => out.push(p[0], p[1], q[0], q[1]);
61
+ if (idx.length === 2)
62
+ emit(pts[idx[0]], pts[idx[1]]);
63
+ else if (idx.length === 4) {
64
+ // saddle: the cell centre decides which corners are connected
65
+ const centre = (s[0] + s[1] + s[2] + s[3]) / 4;
66
+ const p = pts;
67
+ const bottomLeftPositive = s[0] >= 0;
68
+ const joinsCorner0 = centre >= 0 === bottomLeftPositive; // centre agrees with corner 0: corners 0 and 2 are linked through the middle, so the curve cuts off corners 1 and 3
69
+ if (joinsCorner0) {
70
+ emit(p[0], p[1]);
71
+ emit(p[2], p[3]);
72
+ }
73
+ else {
74
+ emit(p[3], p[0]);
75
+ emit(p[1], p[2]);
76
+ }
77
+ }
78
+ });
79
+ }
80
+ [prev, cur] = [cur, prev];
81
+ done++;
82
+ }
83
+ return { segs, progress: progress(done, ny, reason) };
84
+ }
85
+ function toSamples(flat) {
86
+ const n = flat.length / 4;
87
+ const x = new Float64Array(n === 0 ? 0 : n * 3 - 1);
88
+ const y = new Float64Array(x.length);
89
+ for (let s = 0; s < n; s++) {
90
+ const o = s * 3;
91
+ x[o] = flat[4 * s];
92
+ y[o] = flat[4 * s + 1];
93
+ x[o + 1] = flat[4 * s + 2];
94
+ y[o + 1] = flat[4 * s + 3];
95
+ if (s < n - 1) {
96
+ x[o + 2] = Number.NaN;
97
+ y[o + 2] = Number.NaN;
98
+ }
99
+ }
100
+ return { x, y };
101
+ }
102
+ /**
103
+ * The curve `f(x, y) = level` (default 0) by marching squares on a regular grid. A saddle cell is joined by its
104
+ * centre value. Cells with a non-finite corner are skipped (a hole, not a spike). With a budget,
105
+ * `progress.rows` counts grid rows finished.
106
+ */
107
+ export function sampleImplicit(f, xDomain, yDomain, options = {}) {
108
+ const { segs, progress: p } = marching(f, xDomain, yDomain, [options.level ?? 0], options);
109
+ const flat = segs[0];
110
+ return { segments: toSamples(flat), segmentCount: flat.length / 4, progress: p };
111
+ }
112
+ /**
113
+ * Contour lines of `f` at the given `levels`, or `count` (default 9) levels evenly spread strictly between the
114
+ * grid's least and greatest values. One pass over the grid for all levels.
115
+ */
116
+ export function sampleContours(f, xDomain, yDomain, options = {}) {
117
+ let levels = options.levels;
118
+ if (!levels) {
119
+ const [nx, ny] = dims(options.grid);
120
+ let lo = Infinity;
121
+ let hi = -Infinity;
122
+ for (let j = 0; j <= ny; j++)
123
+ for (let i = 0; i <= nx; i++) {
124
+ const v = f(xDomain.min + ((xDomain.max - xDomain.min) * i) / nx, yDomain.min + ((yDomain.max - yDomain.min) * j) / ny);
125
+ if (Number.isFinite(v)) {
126
+ if (v < lo)
127
+ lo = v;
128
+ if (v > hi)
129
+ hi = v;
130
+ }
131
+ }
132
+ const count = options.count ?? 9;
133
+ levels = lo < hi ? Array.from({ length: count }, (_, k) => lo + ((hi - lo) * (k + 1)) / (count + 1)) : [];
134
+ }
135
+ const { segs, progress: p } = marching(f, xDomain, yDomain, levels, options);
136
+ return {
137
+ levels,
138
+ curves: levels.map((level, k) => ({
139
+ level,
140
+ segments: toSamples(segs[k]),
141
+ segmentCount: segs[k].length / 4,
142
+ })),
143
+ progress: p,
144
+ };
145
+ }
146
+ /** Sample the vector field `(fx, fy)` (e.g. the two partial derivatives of a scalar field) on a grid including the edges. */
147
+ export function sampleGradient(fx, fy, xDomain, yDomain, options = {}) {
148
+ const [cols, rws] = typeof options.grid === "number" ? [options.grid, options.grid] : (options.grid ?? [16, 16]);
149
+ assertCount("grid", cols);
150
+ assertCount("grid", rws);
151
+ assertRange("x domain", xDomain);
152
+ assertRange("y domain", yDomain);
153
+ const meter = new Meter(options, options);
154
+ const n = cols * rws;
155
+ const X = new Float64Array(n);
156
+ const Y = new Float64Array(n);
157
+ const U = new Float64Array(n).fill(Number.NaN);
158
+ const V = new Float64Array(n).fill(Number.NaN);
159
+ const M = new Float64Array(n).fill(Number.NaN);
160
+ let done = 0;
161
+ let reason;
162
+ let max = 0;
163
+ for (let j = 0; j < rws; j++) {
164
+ reason = meter.check(cols);
165
+ if (reason)
166
+ break;
167
+ const y = j === rws - 1 ? yDomain.max : yDomain.min + ((yDomain.max - yDomain.min) * j) / (rws - 1);
168
+ for (let i = 0; i < cols; i++) {
169
+ const x = i === cols - 1 ? xDomain.max : xDomain.min + ((xDomain.max - xDomain.min) * i) / (cols - 1);
170
+ const k = j * cols + i;
171
+ X[k] = x;
172
+ Y[k] = y;
173
+ const a = fx(x, y);
174
+ const b = fy(x, y);
175
+ if (Number.isFinite(a) && Number.isFinite(b)) {
176
+ U[k] = a;
177
+ V[k] = b;
178
+ M[k] = Math.hypot(a, b);
179
+ if (M[k] > max)
180
+ max = M[k];
181
+ }
182
+ }
183
+ meter.spend(cols);
184
+ done++;
185
+ }
186
+ const m = cols * done;
187
+ return {
188
+ columns: cols,
189
+ rows: done,
190
+ x: X.slice(0, m),
191
+ y: Y.slice(0, m),
192
+ u: U.slice(0, m),
193
+ v: V.slice(0, m),
194
+ magnitude: M.slice(0, m),
195
+ maxMagnitude: max,
196
+ progress: progress(done, rws, reason),
197
+ };
198
+ }
199
+ //# sourceMappingURL=field2d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field2d.js","sourceRoot":"","sources":["../src/field2d.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type { Budget, Cancellable, Progress } from "./budget.ts";
2
+ export { type ComplexFn, type ComplexRaster, type ComplexRasterOptions, type ConformalGridOptions, type ConformalLine, conformalGrid, findZerosAndPoles, sampleComplexRaster, type ZeroOrPole, type ZerosPoles, type ZerosPolesOptions, } from "./complex.ts";
3
+ export { type Contours, type GradientField, type Grid2Options, type ImplicitCurve, sampleContours, sampleGradient, sampleImplicit, } from "./field2d.ts";
4
+ export { type Curve3, type CurveFn3, type CurveOptions, curve3Runs, type Fn2, type Mesh, type MeshOptions, type ParametricSurfaceFn, sampleParametricSurface, sampleSpaceCurve, sampleSurface, sampleVectorField3, type VectorField3, type VectorField3Options, type VectorFn3, } from "./mesh.ts";
5
+ export { type AdaptiveOdeOptions, classifyFixedPoint, type Field2, type FixedPoint, type FixedPointType, integrateAdaptive, integrateRk4, jacobian2, type OdeOptions, type PhasePortrait, type PhasePortraitOptions, type Rk4Options, type Slope, type SlopeField, type SlopeFieldOptions, type SolutionCurveOptions, type StopReason, type System, samplePhasePortrait, sampleSlopeField, sampleSolutionCurve, type Trajectory, } from "./ode.ts";
6
+ export { type AdaptiveOptions, type CancelSignal, type Domain, type Fn1, findCrossings, findDiscontinuities, findIntersections, findRoots, type Point, type RootOptions, runsOf, SampleCancelledError, type SampleOptions, type Samples, sampleAdaptive, sampleUniform, toPoints, type YRange, } from "./sample.ts";
7
+ export { evaluateFourier, evaluateTaylor, type FourierCoefficients, fourierCoefficients, type NumericSeries, type PartialSumCurves, partialSums, sampleFourierPartialSums, sampleSeriesPartialSums, sampleTaylorPartialSums, } from "./series.ts";
8
+ export { type AxesOptions, axesToSvg, type PathOptions, samplesToSvgPath, svgDocument, type XY } from "./svg.ts";
9
+ export { formatTick, niceTicks, tickStep } from "./ticks.ts";
10
+ export { backingStoreSize, fitViewport, panViewport, pinchZoomFactor, toDataX, toDataY, toScreenX, toScreenY, type Viewport, viewportFromAnchor, wheelZoomFactor, zoomViewport, } from "./viewport.ts";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,aAAa,EACb,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,GAAG,EACR,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,SAAS,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,KAAK,MAAM,EACX,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,GAAG,EACR,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACT,KAAK,KAAK,EACV,KAAK,WAAW,EAChB,MAAM,EACN,oBAAoB,EACpB,KAAK,aAAa,EAClB,KAAK,OAAO,EACZ,cAAc,EACd,aAAa,EACb,QAAQ,EACR,KAAK,MAAM,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,cAAc,EACd,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,WAAW,EACX,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,KAAK,WAAW,EAAE,SAAS,EAAE,KAAK,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,MAAM,UAAU,CAAC;AACjH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,eAAe,EACf,OAAO,EACP,OAAO,EACP,SAAS,EACT,SAAS,EACT,KAAK,QAAQ,EACb,kBAAkB,EAClB,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ export { conformalGrid, findZerosAndPoles, sampleComplexRaster, } from "./complex.js";
2
+ export { sampleContours, sampleGradient, sampleImplicit, } from "./field2d.js";
3
+ export { curve3Runs, sampleParametricSurface, sampleSpaceCurve, sampleSurface, sampleVectorField3, } from "./mesh.js";
4
+ export { classifyFixedPoint, integrateAdaptive, integrateRk4, jacobian2, samplePhasePortrait, sampleSlopeField, sampleSolutionCurve, } from "./ode.js";
5
+ export { findCrossings, findDiscontinuities, findIntersections, findRoots, runsOf, SampleCancelledError, sampleAdaptive, sampleUniform, toPoints, } from "./sample.js";
6
+ export { evaluateFourier, evaluateTaylor, fourierCoefficients, partialSums, sampleFourierPartialSums, sampleSeriesPartialSums, sampleTaylorPartialSums, } from "./series.js";
7
+ export { axesToSvg, samplesToSvgPath, svgDocument } from "./svg.js";
8
+ export { formatTick, niceTicks, tickStep } from "./ticks.js";
9
+ export { backingStoreSize, fitViewport, panViewport, pinchZoomFactor, toDataX, toDataY, toScreenX, toScreenY, viewportFromAnchor, wheelZoomFactor, zoomViewport, } from "./viewport.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAML,aAAa,EACb,iBAAiB,EACjB,mBAAmB,GAIpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAKL,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EAIL,UAAU,EAKV,uBAAuB,EACvB,gBAAgB,EAChB,aAAa,EACb,kBAAkB,GAInB,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,kBAAkB,EAIlB,iBAAiB,EACjB,YAAY,EACZ,SAAS,EAWT,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,UAAU,CAAC;AAClB,OAAO,EAKL,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EAGT,MAAM,EACN,oBAAoB,EAGpB,cAAc,EACd,aAAa,EACb,QAAQ,GAET,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,cAAc,EAEd,mBAAmB,EAGnB,WAAW,EACX,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAoB,SAAS,EAAoB,gBAAgB,EAAE,WAAW,EAAW,MAAM,UAAU,CAAC;AACjH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,eAAe,EACf,OAAO,EACP,OAAO,EACP,SAAS,EACT,SAAS,EAET,kBAAkB,EAClB,eAAe,EACf,YAAY,GACb,MAAM,eAAe,CAAC"}
package/dist/mesh.d.ts ADDED
@@ -0,0 +1,90 @@
1
+ import { type Budget, type Cancellable, type Progress } from "./budget.ts";
2
+ import type { Domain } from "./sample.ts";
3
+ /**
4
+ * Triangle mesh as typed arrays, ready for a GPU buffer.
5
+ *
6
+ * - `positions` and `normals` hold `vertexCount * 3` floats (x, y, z per vertex).
7
+ * - `indices` holds triangles (3 per triangle), counter-clockwise seen from the side the normals point to.
8
+ * - A grid vertex whose position is not finite (or is outside `zRange`) is a hole: its position is `NaN`, its normal
9
+ * is `0, 0, 0`, `valid[v]` is 0, and no triangle references it, so a hole never produces a spike.
10
+ * - `bounds` covers the valid vertices only (`NaN`s if there are none).
11
+ * - `columns` x `rows` is the vertex grid (vertex `(i, j)` is `j * columns + i`), for callers that want to build wireframes.
12
+ */
13
+ export interface Mesh {
14
+ positions: Float32Array;
15
+ normals: Float32Array;
16
+ indices: Uint32Array;
17
+ valid: Uint8Array;
18
+ vertexCount: number;
19
+ columns: number;
20
+ rows: number;
21
+ bounds: {
22
+ min: [number, number, number];
23
+ max: [number, number, number];
24
+ };
25
+ progress: Progress;
26
+ }
27
+ export interface MeshOptions extends Budget, Cancellable {
28
+ /** Vertices along the first parameter (x or u). Default 64. */
29
+ columns?: number;
30
+ /** Vertices along the second parameter (y or v). Default 64. */
31
+ rows?: number;
32
+ /** Vertices with z outside this range are holes (a pole's huge finite shoulders). `z = f(x, y)` only. */
33
+ zRange?: {
34
+ min: number;
35
+ max: number;
36
+ };
37
+ }
38
+ export type Fn2 = (x: number, y: number) => number;
39
+ export type ParametricSurfaceFn = (u: number, v: number) => readonly [number, number, number];
40
+ export type CurveFn3 = (t: number) => readonly [number, number, number];
41
+ export type VectorFn3 = (x: number, y: number, z: number) => readonly [number, number, number];
42
+ /**
43
+ * Sample the surface `z = f(x, y)` on a regular grid. Normals point up (`+z` side). Non-finite values, and
44
+ * values outside `options.zRange`, become holes. When the budget ends early, `rows` is the number of grid
45
+ * rows built and `progress` says why.
46
+ */
47
+ export declare function sampleSurface(f: Fn2, xDomain: Domain, yDomain: Domain, options?: MeshOptions): Mesh;
48
+ /**
49
+ * Sample a parametric surface `(u, v) -> [x, y, z]`. Normals are `dP/du x dP/dv`, so swap the parameters (or
50
+ * negate a component) to flip them. Any non-finite coordinate makes the vertex a hole.
51
+ */
52
+ export declare function sampleParametricSurface(f: ParametricSurfaceFn, uDomain: Domain, vDomain: Domain, options?: MeshOptions): Mesh;
53
+ export interface Curve3 {
54
+ /** `count * 3` doubles. A gap row is `NaN, NaN, NaN`; gaps are never first, last or adjacent to another gap. */
55
+ positions: Float64Array;
56
+ /** The parameter value of each row. */
57
+ t: Float64Array;
58
+ count: number;
59
+ progress: Progress;
60
+ }
61
+ export interface CurveOptions extends Budget, Cancellable {
62
+ /** Samples. Default 512. */
63
+ samples?: number;
64
+ /** Segments longer than this (Euclidean) become gaps, which cuts a curve at a jump. Default: no limit. */
65
+ maxStep?: number;
66
+ }
67
+ /** Sample a space curve `t -> [x, y, z]`; non-finite points become gaps rather than spikes. */
68
+ export declare function sampleSpaceCurve(f: CurveFn3, tDomain: Domain, options?: CurveOptions): Curve3;
69
+ /** Index ranges `[start, end)` of consecutive data rows in a {@link Curve3}. */
70
+ export declare function curve3Runs(c: Curve3): Array<[number, number]>;
71
+ export interface VectorField3 {
72
+ /** `count * 3` floats: arrow tails. */
73
+ origins: Float32Array;
74
+ /** `count * 3` floats: the vector at each tail. */
75
+ vectors: Float32Array;
76
+ magnitudes: Float32Array;
77
+ maxMagnitude: number;
78
+ /** Arrows kept: grid points where the field was finite. */
79
+ count: number;
80
+ /** Grid points skipped because the field was non-finite there. */
81
+ skipped: number;
82
+ progress: Progress;
83
+ }
84
+ export interface VectorField3Options extends Budget, Cancellable {
85
+ /** Points per axis, `[nx, ny, nz]` or one number for all. Default 8. */
86
+ grid?: number | [number, number, number];
87
+ }
88
+ /** Sample a 3D vector field on a regular grid of the box `x` by `y` by `z`. `progress.rows` counts z-slabs. */
89
+ export declare function sampleVectorField3(f: VectorFn3, xDomain: Domain, yDomain: Domain, zDomain: Domain, options?: VectorField3Options): VectorField3;
90
+ //# sourceMappingURL=mesh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../src/mesh.ts"],"names":[],"mappings":"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"}
package/dist/mesh.js ADDED
@@ -0,0 +1,294 @@
1
+ import { assertCount, assertRange, Meter, progress } from "./budget.js";
2
+ const fin = (a, b, c) => Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c);
3
+ function build(evalAt, uDom, vDom, options, rangeZ, flip) {
4
+ const columns = options.columns ?? 64;
5
+ const rows = options.rows ?? 64;
6
+ assertCount("columns", columns);
7
+ assertCount("rows", rows);
8
+ assertRange("u domain", uDom);
9
+ assertRange("v domain", vDom);
10
+ const meter = new Meter(options, options);
11
+ const pos = new Float64Array(columns * rows * 3).fill(Number.NaN);
12
+ const ok = new Uint8Array(columns * rows);
13
+ let done = 0;
14
+ let reason;
15
+ for (let j = 0; j < rows; j++) {
16
+ reason = meter.check(columns);
17
+ if (reason)
18
+ break;
19
+ const v = j === rows - 1 ? vDom.max : vDom.min + ((vDom.max - vDom.min) * j) / (rows - 1);
20
+ for (let i = 0; i < columns; i++) {
21
+ const u = i === columns - 1 ? uDom.max : uDom.min + ((uDom.max - uDom.min) * i) / (columns - 1);
22
+ const p = evalAt(u, v);
23
+ const k = j * columns + i;
24
+ if (fin(p[0], p[1], p[2]) && !(rangeZ && (p[2] < rangeZ.min || p[2] > rangeZ.max))) {
25
+ pos[3 * k] = p[0];
26
+ pos[3 * k + 1] = p[1];
27
+ pos[3 * k + 2] = p[2];
28
+ ok[k] = 1;
29
+ }
30
+ }
31
+ meter.spend(columns);
32
+ done++;
33
+ }
34
+ const usedRows = done;
35
+ const vertexCount = columns * usedRows;
36
+ const positions = new Float32Array(vertexCount * 3);
37
+ const normals = new Float32Array(vertexCount * 3);
38
+ const valid = ok.slice(0, vertexCount);
39
+ const min = [Infinity, Infinity, Infinity];
40
+ const max = [-Infinity, -Infinity, -Infinity];
41
+ for (let k = 0; k < vertexCount; k++) {
42
+ for (let c = 0; c < 3; c++) {
43
+ const val = pos[3 * k + c];
44
+ positions[3 * k + c] = val;
45
+ if (valid[k]) {
46
+ if (val < min[c])
47
+ min[c] = val;
48
+ if (val > max[c])
49
+ max[c] = val;
50
+ }
51
+ }
52
+ }
53
+ // normals: cross of central/one-sided differences over valid neighbours
54
+ const at = (i, j) => 3 * (j * columns + i);
55
+ const isOk = (i, j) => i >= 0 && i < columns && j >= 0 && j < usedRows && valid[j * columns + i] === 1;
56
+ for (let j = 0; j < usedRows; j++) {
57
+ for (let i = 0; i < columns; i++) {
58
+ if (!isOk(i, j))
59
+ continue;
60
+ const iA = isOk(i - 1, j) ? i - 1 : i;
61
+ const iB = isOk(i + 1, j) ? i + 1 : i;
62
+ const jA = isOk(i, j - 1) ? j - 1 : j;
63
+ const jB = isOk(i, j + 1) ? j + 1 : j;
64
+ const du = [0, 1, 2].map((c) => pos[at(iB, j) + c] - pos[at(iA, j) + c]);
65
+ const dv = [0, 1, 2].map((c) => pos[at(i, jB) + c] - pos[at(i, jA) + c]);
66
+ let nx = du[1] * dv[2] - du[2] * dv[1];
67
+ let ny = du[2] * dv[0] - du[0] * dv[2];
68
+ let nz = du[0] * dv[1] - du[1] * dv[0];
69
+ const len = Math.hypot(nx, ny, nz);
70
+ if (len > 0 && Number.isFinite(len)) {
71
+ const s = (flip ? -1 : 1) / len;
72
+ nx *= s;
73
+ ny *= s;
74
+ nz *= s;
75
+ const o = at(i, j);
76
+ normals[o] = nx;
77
+ normals[o + 1] = ny;
78
+ normals[o + 2] = nz;
79
+ }
80
+ }
81
+ }
82
+ // valid vertices with a degenerate normal (the poles of a sphere parameterisation): borrow from a neighbour
83
+ for (let j = 0; j < usedRows; j++) {
84
+ for (let i = 0; i < columns; i++) {
85
+ const o = at(i, j);
86
+ if (!isOk(i, j) || normals[o] !== 0 || normals[o + 1] !== 0 || normals[o + 2] !== 0)
87
+ continue;
88
+ for (const [di, dj] of [
89
+ [0, 1],
90
+ [0, -1],
91
+ [1, 0],
92
+ [-1, 0],
93
+ [0, 2],
94
+ [0, -2],
95
+ ]) {
96
+ if (!isOk(i + di, j + dj))
97
+ continue;
98
+ const q = at(i + di, j + dj);
99
+ if (normals[q] !== 0 || normals[q + 1] !== 0 || normals[q + 2] !== 0) {
100
+ normals[o] = normals[q];
101
+ normals[o + 1] = normals[q + 1];
102
+ normals[o + 2] = normals[q + 2];
103
+ break;
104
+ }
105
+ }
106
+ }
107
+ }
108
+ if (!valid.some((x) => x === 1)) {
109
+ for (let c = 0; c < 3; c++) {
110
+ min[c] = Number.NaN;
111
+ max[c] = Number.NaN;
112
+ }
113
+ }
114
+ const tri = [];
115
+ for (let j = 0; j + 1 < usedRows; j++) {
116
+ for (let i = 0; i + 1 < columns; i++) {
117
+ const a = j * columns + i;
118
+ const b = a + 1;
119
+ const c = a + columns;
120
+ const d = c + 1;
121
+ const [va, vb, vc, vd] = [valid[a], valid[b], valid[c], valid[d]];
122
+ // counter-clockwise in (u, v): a, b, d and a, d, c
123
+ if (va && vb && vd)
124
+ tri.push(a, b, d);
125
+ if (va && vd && vc)
126
+ tri.push(a, d, c);
127
+ // a quad with exactly one hole corner still yields its one good triangle via the complementary split
128
+ if (!(va && vb && vd) && !(va && vd && vc)) {
129
+ if (va && vb && vc)
130
+ tri.push(a, b, c);
131
+ else if (vb && vd && vc)
132
+ tri.push(b, d, c);
133
+ }
134
+ }
135
+ }
136
+ return {
137
+ positions,
138
+ normals,
139
+ indices: Uint32Array.from(tri),
140
+ valid,
141
+ vertexCount,
142
+ columns,
143
+ rows: usedRows,
144
+ bounds: { min, max },
145
+ progress: progress(usedRows, rows, reason),
146
+ };
147
+ }
148
+ /**
149
+ * Sample the surface `z = f(x, y)` on a regular grid. Normals point up (`+z` side). Non-finite values, and
150
+ * values outside `options.zRange`, become holes. When the budget ends early, `rows` is the number of grid
151
+ * rows built and `progress` says why.
152
+ */
153
+ export function sampleSurface(f, xDomain, yDomain, options = {}) {
154
+ return build((x, y) => [x, y, f(x, y)], xDomain, yDomain, options, options.zRange, false);
155
+ }
156
+ /**
157
+ * Sample a parametric surface `(u, v) -> [x, y, z]`. Normals are `dP/du x dP/dv`, so swap the parameters (or
158
+ * negate a component) to flip them. Any non-finite coordinate makes the vertex a hole.
159
+ */
160
+ export function sampleParametricSurface(f, uDomain, vDomain, options = {}) {
161
+ return build(f, uDomain, vDomain, { ...options, zRange: undefined }, undefined, false);
162
+ }
163
+ /** Sample a space curve `t -> [x, y, z]`; non-finite points become gaps rather than spikes. */
164
+ export function sampleSpaceCurve(f, tDomain, options = {}) {
165
+ const n = options.samples ?? 512;
166
+ assertCount("samples", n);
167
+ assertRange("t domain", tDomain);
168
+ const meter = new Meter(options, options);
169
+ const rows = [];
170
+ const ts = [];
171
+ let done = 0;
172
+ let reason;
173
+ const CHUNK = 256;
174
+ for (let k = 0; k < n; k++) {
175
+ if (k % CHUNK === 0) {
176
+ reason = meter.check(Math.min(CHUNK, n - k));
177
+ if (reason)
178
+ break;
179
+ }
180
+ const t = k === n - 1 ? tDomain.max : tDomain.min + ((tDomain.max - tDomain.min) * k) / (n - 1);
181
+ const p = f(t);
182
+ ts.push(t);
183
+ rows.push(fin(p[0], p[1], p[2]) ? p[0] : Number.NaN, p[1], p[2]);
184
+ meter.spend(1);
185
+ done++;
186
+ }
187
+ // gap rule: NaN rows, with maxStep cuts, no leading/trailing/adjacent gaps
188
+ const outP = [];
189
+ const outT = [];
190
+ let prev; // index into rows of previous valid row
191
+ let pendingGap = false;
192
+ for (let k = 0; k < done; k++) {
193
+ const x = rows[3 * k];
194
+ if (Number.isNaN(x)) {
195
+ pendingGap = outP.length > 0;
196
+ prev = undefined;
197
+ continue;
198
+ }
199
+ const y = rows[3 * k + 1];
200
+ const z = rows[3 * k + 2];
201
+ let gap = pendingGap;
202
+ if (prev !== undefined && options.maxStep !== undefined) {
203
+ const d = Math.hypot(x - rows[3 * prev], y - rows[3 * prev + 1], z - rows[3 * prev + 2]);
204
+ if (d > options.maxStep)
205
+ gap = true;
206
+ }
207
+ if (gap && outP.length > 0) {
208
+ outP.push(Number.NaN, Number.NaN, Number.NaN);
209
+ outT.push(Number.NaN);
210
+ }
211
+ outP.push(x, y, z);
212
+ outT.push(ts[k]);
213
+ prev = k;
214
+ pendingGap = false;
215
+ }
216
+ return {
217
+ positions: Float64Array.from(outP),
218
+ t: Float64Array.from(outT),
219
+ count: outT.length,
220
+ progress: progress(done, n, reason),
221
+ };
222
+ }
223
+ /** Index ranges `[start, end)` of consecutive data rows in a {@link Curve3}. */
224
+ export function curve3Runs(c) {
225
+ const runs = [];
226
+ let start = -1;
227
+ for (let k = 0; k < c.count; k++) {
228
+ if (Number.isNaN(c.positions[3 * k])) {
229
+ if (start >= 0)
230
+ runs.push([start, k]);
231
+ start = -1;
232
+ }
233
+ else if (start < 0)
234
+ start = k;
235
+ }
236
+ if (start >= 0)
237
+ runs.push([start, c.count]);
238
+ return runs;
239
+ }
240
+ /** Sample a 3D vector field on a regular grid of the box `x` by `y` by `z`. `progress.rows` counts z-slabs. */
241
+ export function sampleVectorField3(f, xDomain, yDomain, zDomain, options = {}) {
242
+ const g = options.grid ?? 8;
243
+ const [nx, ny, nz] = typeof g === "number" ? [g, g, g] : g;
244
+ assertCount("grid", nx);
245
+ assertCount("grid", ny);
246
+ assertCount("grid", nz);
247
+ assertRange("x domain", xDomain);
248
+ assertRange("y domain", yDomain);
249
+ assertRange("z domain", zDomain);
250
+ const meter = new Meter(options, options);
251
+ const o = [];
252
+ const vs = [];
253
+ const mags = [];
254
+ let skipped = 0;
255
+ let slabs = 0;
256
+ let reason;
257
+ const lerp = (d, k, n) => (k === n - 1 ? d.max : d.min + ((d.max - d.min) * k) / (n - 1));
258
+ for (let kz = 0; kz < nz; kz++) {
259
+ reason = meter.check(nx * ny);
260
+ if (reason)
261
+ break;
262
+ for (let jy = 0; jy < ny; jy++) {
263
+ for (let ix = 0; ix < nx; ix++) {
264
+ const x = lerp(xDomain, ix, nx);
265
+ const y = lerp(yDomain, jy, ny);
266
+ const z = lerp(zDomain, kz, nz);
267
+ const v = f(x, y, z);
268
+ if (!fin(v[0], v[1], v[2])) {
269
+ skipped++;
270
+ continue;
271
+ }
272
+ o.push(x, y, z);
273
+ vs.push(v[0], v[1], v[2]);
274
+ mags.push(Math.hypot(v[0], v[1], v[2]));
275
+ }
276
+ }
277
+ meter.spend(nx * ny);
278
+ slabs++;
279
+ }
280
+ let maxMagnitude = 0;
281
+ for (const m of mags)
282
+ if (m > maxMagnitude)
283
+ maxMagnitude = m;
284
+ return {
285
+ origins: Float32Array.from(o),
286
+ vectors: Float32Array.from(vs),
287
+ magnitudes: Float32Array.from(mags),
288
+ maxMagnitude,
289
+ count: mags.length,
290
+ skipped,
291
+ progress: progress(slabs, nz, reason),
292
+ };
293
+ }
294
+ //# sourceMappingURL=mesh.js.map