interactive-bg 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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -2
  3. package/dist/core/canvas2d-renderer.cjs +119 -0
  4. package/dist/core/canvas2d-renderer.cjs.map +1 -0
  5. package/dist/core/canvas2d-renderer.d.cts +7 -0
  6. package/dist/core/canvas2d-renderer.d.ts +7 -0
  7. package/dist/core/canvas2d-renderer.js +119 -0
  8. package/dist/core/canvas2d-renderer.js.map +1 -0
  9. package/dist/core/color.cjs +46 -0
  10. package/dist/core/color.cjs.map +1 -0
  11. package/dist/core/color.d.cts +6 -0
  12. package/dist/core/color.d.ts +6 -0
  13. package/dist/core/color.js +46 -0
  14. package/dist/core/color.js.map +1 -0
  15. package/dist/core/engine.cjs +367 -0
  16. package/dist/core/engine.cjs.map +1 -0
  17. package/dist/core/engine.d.cts +69 -0
  18. package/dist/core/engine.d.ts +69 -0
  19. package/dist/core/engine.js +366 -0
  20. package/dist/core/engine.js.map +1 -0
  21. package/dist/core/style.cjs +21 -0
  22. package/dist/core/style.cjs.map +1 -0
  23. package/dist/core/style.d.cts +85 -0
  24. package/dist/core/style.d.ts +85 -0
  25. package/dist/core/style.js +21 -0
  26. package/dist/core/style.js.map +1 -0
  27. package/dist/core/surface.cjs +25 -0
  28. package/dist/core/surface.cjs.map +1 -0
  29. package/dist/core/surface.d.cts +42 -0
  30. package/dist/core/surface.d.ts +42 -0
  31. package/dist/core/surface.js +24 -0
  32. package/dist/core/surface.js.map +1 -0
  33. package/dist/core/webgl-renderer.cjs +137 -0
  34. package/dist/core/webgl-renderer.cjs.map +1 -0
  35. package/dist/core/webgl-renderer.d.cts +8 -0
  36. package/dist/core/webgl-renderer.d.ts +8 -0
  37. package/dist/core/webgl-renderer.js +137 -0
  38. package/dist/core/webgl-renderer.js.map +1 -0
  39. package/dist/core/webgl.cjs +62 -0
  40. package/dist/core/webgl.cjs.map +1 -0
  41. package/dist/core/webgl.d.cts +15 -0
  42. package/dist/core/webgl.d.ts +15 -0
  43. package/dist/core/webgl.js +60 -0
  44. package/dist/core/webgl.js.map +1 -0
  45. package/dist/dots/canvas2d.cjs +14 -0
  46. package/dist/dots/canvas2d.cjs.map +1 -0
  47. package/dist/dots/canvas2d.d.cts +5 -0
  48. package/dist/dots/canvas2d.d.ts +5 -0
  49. package/dist/dots/canvas2d.js +13 -0
  50. package/dist/dots/canvas2d.js.map +1 -0
  51. package/dist/dots/index.cjs +16 -0
  52. package/dist/dots/index.cjs.map +1 -0
  53. package/dist/dots/index.d.cts +5 -0
  54. package/dist/dots/index.d.ts +5 -0
  55. package/dist/dots/index.js +15 -0
  56. package/dist/dots/index.js.map +1 -0
  57. package/dist/dots/webgl.cjs +14 -0
  58. package/dist/dots/webgl.cjs.map +1 -0
  59. package/dist/dots/webgl.d.cts +5 -0
  60. package/dist/dots/webgl.d.ts +5 -0
  61. package/dist/dots/webgl.js +13 -0
  62. package/dist/dots/webgl.js.map +1 -0
  63. package/dist/index.cjs +24 -0
  64. package/dist/index.d.cts +18 -0
  65. package/dist/index.d.ts +18 -0
  66. package/dist/index.js +11 -0
  67. package/dist/index.umd.js +211 -0
  68. package/dist/index.umd.js.map +1 -0
  69. package/dist/plus/canvas2d.cjs +14 -0
  70. package/dist/plus/canvas2d.cjs.map +1 -0
  71. package/dist/plus/canvas2d.d.cts +5 -0
  72. package/dist/plus/canvas2d.d.ts +5 -0
  73. package/dist/plus/canvas2d.js +13 -0
  74. package/dist/plus/canvas2d.js.map +1 -0
  75. package/dist/plus/index.cjs +16 -0
  76. package/dist/plus/index.cjs.map +1 -0
  77. package/dist/plus/index.d.cts +5 -0
  78. package/dist/plus/index.d.ts +5 -0
  79. package/dist/plus/index.js +15 -0
  80. package/dist/plus/index.js.map +1 -0
  81. package/dist/plus/webgl.cjs +14 -0
  82. package/dist/plus/webgl.cjs.map +1 -0
  83. package/dist/plus/webgl.d.cts +5 -0
  84. package/dist/plus/webgl.d.ts +5 -0
  85. package/dist/plus/webgl.js +13 -0
  86. package/dist/plus/webgl.js.map +1 -0
  87. package/dist/shared/buffer.cjs +20 -0
  88. package/dist/shared/buffer.cjs.map +1 -0
  89. package/dist/shared/buffer.d.cts +11 -0
  90. package/dist/shared/buffer.d.ts +11 -0
  91. package/dist/shared/buffer.js +19 -0
  92. package/dist/shared/buffer.js.map +1 -0
  93. package/dist/shared/grid-webgl.cjs +63 -0
  94. package/dist/shared/grid-webgl.cjs.map +1 -0
  95. package/dist/shared/grid-webgl.d.cts +10 -0
  96. package/dist/shared/grid-webgl.d.ts +10 -0
  97. package/dist/shared/grid-webgl.js +61 -0
  98. package/dist/shared/grid-webgl.js.map +1 -0
  99. package/dist/shared/grid.cjs +133 -0
  100. package/dist/shared/grid.cjs.map +1 -0
  101. package/dist/shared/grid.d.cts +72 -0
  102. package/dist/shared/grid.d.ts +72 -0
  103. package/dist/shared/grid.js +123 -0
  104. package/dist/shared/grid.js.map +1 -0
  105. package/dist/shared/noise.cjs +166 -0
  106. package/dist/shared/noise.cjs.map +1 -0
  107. package/dist/shared/noise.d.cts +4 -0
  108. package/dist/shared/noise.d.ts +4 -0
  109. package/dist/shared/noise.js +166 -0
  110. package/dist/shared/noise.js.map +1 -0
  111. package/dist/styles/dots/canvas2d.cjs +99 -0
  112. package/dist/styles/dots/canvas2d.cjs.map +1 -0
  113. package/dist/styles/dots/canvas2d.d.cts +7 -0
  114. package/dist/styles/dots/canvas2d.d.ts +7 -0
  115. package/dist/styles/dots/canvas2d.js +99 -0
  116. package/dist/styles/dots/canvas2d.js.map +1 -0
  117. package/dist/styles/dots/definition.cjs +15 -0
  118. package/dist/styles/dots/definition.cjs.map +1 -0
  119. package/dist/styles/dots/definition.d.cts +7 -0
  120. package/dist/styles/dots/definition.d.ts +7 -0
  121. package/dist/styles/dots/definition.js +16 -0
  122. package/dist/styles/dots/definition.js.map +1 -0
  123. package/dist/styles/dots/motion.cjs +6 -0
  124. package/dist/styles/dots/motion.cjs.map +1 -0
  125. package/dist/styles/dots/motion.d.cts +2 -0
  126. package/dist/styles/dots/motion.d.ts +2 -0
  127. package/dist/styles/dots/motion.js +6 -0
  128. package/dist/styles/dots/motion.js.map +1 -0
  129. package/dist/styles/dots/options.cjs +33 -0
  130. package/dist/styles/dots/options.cjs.map +1 -0
  131. package/dist/styles/dots/options.d.cts +33 -0
  132. package/dist/styles/dots/options.d.ts +33 -0
  133. package/dist/styles/dots/options.js +32 -0
  134. package/dist/styles/dots/options.js.map +1 -0
  135. package/dist/styles/dots/webgl.cjs +113 -0
  136. package/dist/styles/dots/webgl.cjs.map +1 -0
  137. package/dist/styles/dots/webgl.d.cts +4 -0
  138. package/dist/styles/dots/webgl.d.ts +4 -0
  139. package/dist/styles/dots/webgl.js +113 -0
  140. package/dist/styles/dots/webgl.js.map +1 -0
  141. package/dist/styles/plus/canvas2d.cjs +88 -0
  142. package/dist/styles/plus/canvas2d.cjs.map +1 -0
  143. package/dist/styles/plus/canvas2d.d.cts +8 -0
  144. package/dist/styles/plus/canvas2d.d.ts +8 -0
  145. package/dist/styles/plus/canvas2d.js +88 -0
  146. package/dist/styles/plus/canvas2d.js.map +1 -0
  147. package/dist/styles/plus/definition.cjs +17 -0
  148. package/dist/styles/plus/definition.cjs.map +1 -0
  149. package/dist/styles/plus/definition.d.cts +9 -0
  150. package/dist/styles/plus/definition.d.ts +9 -0
  151. package/dist/styles/plus/definition.js +18 -0
  152. package/dist/styles/plus/definition.js.map +1 -0
  153. package/dist/styles/plus/motion.cjs +18 -0
  154. package/dist/styles/plus/motion.cjs.map +1 -0
  155. package/dist/styles/plus/motion.d.cts +5 -0
  156. package/dist/styles/plus/motion.d.ts +5 -0
  157. package/dist/styles/plus/motion.js +18 -0
  158. package/dist/styles/plus/motion.js.map +1 -0
  159. package/dist/styles/plus/options.cjs +45 -0
  160. package/dist/styles/plus/options.cjs.map +1 -0
  161. package/dist/styles/plus/options.d.cts +45 -0
  162. package/dist/styles/plus/options.d.ts +45 -0
  163. package/dist/styles/plus/options.js +43 -0
  164. package/dist/styles/plus/options.js.map +1 -0
  165. package/dist/styles/plus/turns.cjs +102 -0
  166. package/dist/styles/plus/turns.cjs.map +1 -0
  167. package/dist/styles/plus/turns.d.cts +17 -0
  168. package/dist/styles/plus/turns.d.ts +17 -0
  169. package/dist/styles/plus/turns.js +102 -0
  170. package/dist/styles/plus/turns.js.map +1 -0
  171. package/dist/styles/plus/webgl.cjs +121 -0
  172. package/dist/styles/plus/webgl.cjs.map +1 -0
  173. package/dist/styles/plus/webgl.d.cts +8 -0
  174. package/dist/styles/plus/webgl.d.ts +8 -0
  175. package/dist/styles/plus/webgl.js +121 -0
  176. package/dist/styles/plus/webgl.js.map +1 -0
  177. package/dist/styles/topo/canvas2d.cjs +77 -0
  178. package/dist/styles/topo/canvas2d.cjs.map +1 -0
  179. package/dist/styles/topo/canvas2d.d.cts +4 -0
  180. package/dist/styles/topo/canvas2d.d.ts +4 -0
  181. package/dist/styles/topo/canvas2d.js +77 -0
  182. package/dist/styles/topo/canvas2d.js.map +1 -0
  183. package/dist/styles/topo/contours.cjs +83 -0
  184. package/dist/styles/topo/contours.cjs.map +1 -0
  185. package/dist/styles/topo/contours.d.cts +9 -0
  186. package/dist/styles/topo/contours.d.ts +9 -0
  187. package/dist/styles/topo/contours.js +83 -0
  188. package/dist/styles/topo/contours.js.map +1 -0
  189. package/dist/styles/topo/definition.cjs +13 -0
  190. package/dist/styles/topo/definition.cjs.map +1 -0
  191. package/dist/styles/topo/definition.d.cts +7 -0
  192. package/dist/styles/topo/definition.d.ts +7 -0
  193. package/dist/styles/topo/definition.js +14 -0
  194. package/dist/styles/topo/definition.js.map +1 -0
  195. package/dist/styles/topo/field.cjs +118 -0
  196. package/dist/styles/topo/field.cjs.map +1 -0
  197. package/dist/styles/topo/field.d.cts +26 -0
  198. package/dist/styles/topo/field.d.ts +26 -0
  199. package/dist/styles/topo/field.js +118 -0
  200. package/dist/styles/topo/field.js.map +1 -0
  201. package/dist/styles/topo/options.cjs +39 -0
  202. package/dist/styles/topo/options.cjs.map +1 -0
  203. package/dist/styles/topo/options.d.cts +52 -0
  204. package/dist/styles/topo/options.d.ts +52 -0
  205. package/dist/styles/topo/options.js +38 -0
  206. package/dist/styles/topo/options.js.map +1 -0
  207. package/dist/styles/topo/terrain.cjs +22 -0
  208. package/dist/styles/topo/terrain.cjs.map +1 -0
  209. package/dist/styles/topo/terrain.d.cts +11 -0
  210. package/dist/styles/topo/terrain.d.ts +11 -0
  211. package/dist/styles/topo/terrain.js +22 -0
  212. package/dist/styles/topo/terrain.js.map +1 -0
  213. package/dist/styles/topo/webgl.cjs +150 -0
  214. package/dist/styles/topo/webgl.cjs.map +1 -0
  215. package/dist/styles/topo/webgl.d.cts +7 -0
  216. package/dist/styles/topo/webgl.d.ts +7 -0
  217. package/dist/styles/topo/webgl.js +150 -0
  218. package/dist/styles/topo/webgl.js.map +1 -0
  219. package/dist/topo/canvas2d.cjs +14 -0
  220. package/dist/topo/canvas2d.cjs.map +1 -0
  221. package/dist/topo/canvas2d.d.cts +5 -0
  222. package/dist/topo/canvas2d.d.ts +5 -0
  223. package/dist/topo/canvas2d.js +13 -0
  224. package/dist/topo/canvas2d.js.map +1 -0
  225. package/dist/topo/index.cjs +16 -0
  226. package/dist/topo/index.cjs.map +1 -0
  227. package/dist/topo/index.d.cts +5 -0
  228. package/dist/topo/index.d.ts +5 -0
  229. package/dist/topo/index.js +15 -0
  230. package/dist/topo/index.js.map +1 -0
  231. package/dist/topo/webgl.cjs +14 -0
  232. package/dist/topo/webgl.cjs.map +1 -0
  233. package/dist/topo/webgl.d.cts +5 -0
  234. package/dist/topo/webgl.d.ts +5 -0
  235. package/dist/topo/webgl.js +13 -0
  236. package/dist/topo/webgl.js.map +1 -0
  237. package/package.json +192 -4
@@ -0,0 +1,83 @@
1
+ // src/styles/topo/contours.ts
2
+ /**
3
+ * Marching squares over a regular grid of samples.
4
+ *
5
+ * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`
6
+ * apart. Contour lines are traced at every multiple of `step`; each segment is
7
+ * passed to `emit` together with its integer level index (threshold / step).
8
+ */
9
+ function traceContours(field, cols, rows, cellSize, step, emit) {
10
+ if (step <= 0) return;
11
+ for (let j = 0; j < rows - 1; j++) {
12
+ const y0 = j * cellSize;
13
+ const y1 = y0 + cellSize;
14
+ for (let i = 0; i < cols - 1; i++) {
15
+ const idx = j * cols + i;
16
+ const a = field[idx];
17
+ const b = field[idx + 1];
18
+ const c = field[idx + cols + 1];
19
+ const d = field[idx + cols];
20
+ const min = Math.min(a, b, c, d);
21
+ const max = Math.max(a, b, c, d);
22
+ const first = Math.ceil(min / step);
23
+ const last = Math.floor(max / step);
24
+ if (first > last) continue;
25
+ const x0 = i * cellSize;
26
+ const x1 = x0 + cellSize;
27
+ for (let level = first; level <= last; level++) {
28
+ const t = level * step;
29
+ const code = (a >= t ? 8 : 0) | (b >= t ? 4 : 0) | (c >= t ? 2 : 0) | (d >= t ? 1 : 0);
30
+ if (code === 0 || code === 15) continue;
31
+ const topX = x0 + cellSize * frac(t, a, b);
32
+ const rightY = y0 + cellSize * frac(t, b, c);
33
+ const bottomX = x0 + cellSize * frac(t, d, c);
34
+ const leftY = y0 + cellSize * frac(t, a, d);
35
+ switch (code) {
36
+ case 1:
37
+ case 14:
38
+ emit(x0, leftY, bottomX, y1, level);
39
+ break;
40
+ case 2:
41
+ case 13:
42
+ emit(bottomX, y1, x1, rightY, level);
43
+ break;
44
+ case 3:
45
+ case 12:
46
+ emit(x0, leftY, x1, rightY, level);
47
+ break;
48
+ case 4:
49
+ case 11:
50
+ emit(topX, y0, x1, rightY, level);
51
+ break;
52
+ case 6:
53
+ case 9:
54
+ emit(topX, y0, bottomX, y1, level);
55
+ break;
56
+ case 7:
57
+ case 8:
58
+ emit(x0, leftY, topX, y0, level);
59
+ break;
60
+ case 5:
61
+ case 10: {
62
+ const centreAbove = (a + b + c + d) / 4 >= t;
63
+ if (code === 5 === centreAbove) {
64
+ emit(x0, leftY, topX, y0, level);
65
+ emit(bottomX, y1, x1, rightY, level);
66
+ } else {
67
+ emit(topX, y0, x1, rightY, level);
68
+ emit(x0, leftY, bottomX, y1, level);
69
+ }
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ function frac(t, from, to) {
78
+ const d = to - from;
79
+ return d === 0 ? .5 : (t - from) / d;
80
+ }
81
+ exports.traceContours = traceContours;
82
+
83
+ //# sourceMappingURL=contours.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contours.cjs","names":[],"sources":["../../../src/styles/topo/contours.ts"],"sourcesContent":["export type SegmentSink = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n level: number,\n) => void;\n\n/**\n * Marching squares over a regular grid of samples.\n *\n * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`\n * apart. Contour lines are traced at every multiple of `step`; each segment is\n * passed to `emit` together with its integer level index (threshold / step).\n */\nexport function traceContours(\n field: ArrayLike<number>,\n cols: number,\n rows: number,\n cellSize: number,\n step: number,\n emit: SegmentSink,\n): void {\n if (step <= 0) return;\n\n for (let j = 0; j < rows - 1; j++) {\n const y0 = j * cellSize;\n const y1 = y0 + cellSize;\n for (let i = 0; i < cols - 1; i++) {\n const idx = j * cols + i;\n // a ── b\n // │ │\n // d ── c\n const a = field[idx];\n const b = field[idx + 1];\n const c = field[idx + cols + 1];\n const d = field[idx + cols];\n\n const min = Math.min(a, b, c, d);\n const max = Math.max(a, b, c, d);\n const first = Math.ceil(min / step);\n const last = Math.floor(max / step);\n if (first > last) continue;\n\n const x0 = i * cellSize;\n const x1 = x0 + cellSize;\n\n for (let level = first; level <= last; level++) {\n const t = level * step;\n const code =\n (a >= t ? 8 : 0) | (b >= t ? 4 : 0) | (c >= t ? 2 : 0) | (d >= t ? 1 : 0);\n if (code === 0 || code === 15) continue;\n\n // Crossing points on each edge (only valid when that edge is crossed).\n const topX = x0 + cellSize * frac(t, a, b);\n const rightY = y0 + cellSize * frac(t, b, c);\n const bottomX = x0 + cellSize * frac(t, d, c);\n const leftY = y0 + cellSize * frac(t, a, d);\n\n switch (code) {\n case 1:\n case 14:\n emit(x0, leftY, bottomX, y1, level);\n break;\n case 2:\n case 13:\n emit(bottomX, y1, x1, rightY, level);\n break;\n case 3:\n case 12:\n emit(x0, leftY, x1, rightY, level);\n break;\n case 4:\n case 11:\n emit(topX, y0, x1, rightY, level);\n break;\n case 6:\n case 9:\n emit(topX, y0, bottomX, y1, level);\n break;\n case 7:\n case 8:\n emit(x0, leftY, topX, y0, level);\n break;\n case 5:\n case 10: {\n // Saddle: disambiguate with the cell centre.\n const centreAbove = (a + b + c + d) / 4 >= t;\n const isolateAC = (code === 5) === centreAbove;\n if (isolateAC) {\n emit(x0, leftY, topX, y0, level);\n emit(bottomX, y1, x1, rightY, level);\n } else {\n emit(topX, y0, x1, rightY, level);\n emit(x0, leftY, bottomX, y1, level);\n }\n break;\n }\n }\n }\n }\n }\n}\n\nfunction frac(t: number, from: number, to: number): number {\n const d = to - from;\n return d === 0 ? 0.5 : (t - from) / d;\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,cACd,OACA,MACA,MACA,UACA,MACA,MACM;CACN,IAAI,QAAQ,GAAG;CAEf,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK;EACjC,MAAM,KAAK,IAAI;EACf,MAAM,KAAK,KAAK;EAChB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK;GACjC,MAAM,MAAM,IAAI,OAAO;GAIvB,MAAM,IAAI,MAAM;GAChB,MAAM,IAAI,MAAM,MAAM;GACtB,MAAM,IAAI,MAAM,MAAM,OAAO;GAC7B,MAAM,IAAI,MAAM,MAAM;GAEtB,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;GAC/B,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;GAC/B,MAAM,QAAQ,KAAK,KAAK,MAAM,IAAI;GAClC,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI;GAClC,IAAI,QAAQ,MAAM;GAElB,MAAM,KAAK,IAAI;GACf,MAAM,KAAK,KAAK;GAEhB,KAAK,IAAI,QAAQ,OAAO,SAAS,MAAM,SAAS;IAC9C,MAAM,IAAI,QAAQ;IAClB,MAAM,QACH,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI;IACzE,IAAI,SAAS,KAAK,SAAS,IAAI;IAG/B,MAAM,OAAO,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IACzC,MAAM,SAAS,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAC3C,MAAM,UAAU,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAC5C,MAAM,QAAQ,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAE1C,QAAQ,MAAR;KACE,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,SAAS,IAAI,KAAK;MAClC;KACF,KAAK;KACL,KAAK;MACH,KAAK,SAAS,IAAI,IAAI,QAAQ,KAAK;MACnC;KACF,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,IAAI,QAAQ,KAAK;MACjC;KACF,KAAK;KACL,KAAK;MACH,KAAK,MAAM,IAAI,IAAI,QAAQ,KAAK;MAChC;KACF,KAAK;KACL,KAAK;MACH,KAAK,MAAM,IAAI,SAAS,IAAI,KAAK;MACjC;KACF,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,MAAM,IAAI,KAAK;MAC/B;KACF,KAAK;KACL,KAAK,IAAI;MAEP,MAAM,eAAe,IAAI,IAAI,IAAI,KAAK,KAAK;MAE3C,IADmB,SAAS,MAAO,aACpB;OACb,KAAK,IAAI,OAAO,MAAM,IAAI,KAAK;OAC/B,KAAK,SAAS,IAAI,IAAI,QAAQ,KAAK;MACrC,OAAO;OACL,KAAK,MAAM,IAAI,IAAI,QAAQ,KAAK;OAChC,KAAK,IAAI,OAAO,SAAS,IAAI,KAAK;MACpC;MACA;KACF;IACF;GACF;EACF;CACF;AACF;AAEA,SAAS,KAAK,GAAW,MAAc,IAAoB;CACzD,MAAM,IAAI,KAAK;CACf,OAAO,MAAM,IAAI,MAAO,IAAI,QAAQ;AACtC"}
@@ -0,0 +1,9 @@
1
+ export type SegmentSink = (x1: number, y1: number, x2: number, y2: number, level: number) => void;
2
+ /**
3
+ * Marching squares over a regular grid of samples.
4
+ *
5
+ * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`
6
+ * apart. Contour lines are traced at every multiple of `step`; each segment is
7
+ * passed to `emit` together with its integer level index (threshold / step).
8
+ */
9
+ export declare function traceContours(field: ArrayLike<number>, cols: number, rows: number, cellSize: number, step: number, emit: SegmentSink): void;
@@ -0,0 +1,9 @@
1
+ export type SegmentSink = (x1: number, y1: number, x2: number, y2: number, level: number) => void;
2
+ /**
3
+ * Marching squares over a regular grid of samples.
4
+ *
5
+ * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`
6
+ * apart. Contour lines are traced at every multiple of `step`; each segment is
7
+ * passed to `emit` together with its integer level index (threshold / step).
8
+ */
9
+ export declare function traceContours(field: ArrayLike<number>, cols: number, rows: number, cellSize: number, step: number, emit: SegmentSink): void;
@@ -0,0 +1,83 @@
1
+ // src/styles/topo/contours.ts
2
+ /**
3
+ * Marching squares over a regular grid of samples.
4
+ *
5
+ * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`
6
+ * apart. Contour lines are traced at every multiple of `step`; each segment is
7
+ * passed to `emit` together with its integer level index (threshold / step).
8
+ */
9
+ function traceContours(field, cols, rows, cellSize, step, emit) {
10
+ if (step <= 0) return;
11
+ for (let j = 0; j < rows - 1; j++) {
12
+ const y0 = j * cellSize;
13
+ const y1 = y0 + cellSize;
14
+ for (let i = 0; i < cols - 1; i++) {
15
+ const idx = j * cols + i;
16
+ const a = field[idx];
17
+ const b = field[idx + 1];
18
+ const c = field[idx + cols + 1];
19
+ const d = field[idx + cols];
20
+ const min = Math.min(a, b, c, d);
21
+ const max = Math.max(a, b, c, d);
22
+ const first = Math.ceil(min / step);
23
+ const last = Math.floor(max / step);
24
+ if (first > last) continue;
25
+ const x0 = i * cellSize;
26
+ const x1 = x0 + cellSize;
27
+ for (let level = first; level <= last; level++) {
28
+ const t = level * step;
29
+ const code = (a >= t ? 8 : 0) | (b >= t ? 4 : 0) | (c >= t ? 2 : 0) | (d >= t ? 1 : 0);
30
+ if (code === 0 || code === 15) continue;
31
+ const topX = x0 + cellSize * frac(t, a, b);
32
+ const rightY = y0 + cellSize * frac(t, b, c);
33
+ const bottomX = x0 + cellSize * frac(t, d, c);
34
+ const leftY = y0 + cellSize * frac(t, a, d);
35
+ switch (code) {
36
+ case 1:
37
+ case 14:
38
+ emit(x0, leftY, bottomX, y1, level);
39
+ break;
40
+ case 2:
41
+ case 13:
42
+ emit(bottomX, y1, x1, rightY, level);
43
+ break;
44
+ case 3:
45
+ case 12:
46
+ emit(x0, leftY, x1, rightY, level);
47
+ break;
48
+ case 4:
49
+ case 11:
50
+ emit(topX, y0, x1, rightY, level);
51
+ break;
52
+ case 6:
53
+ case 9:
54
+ emit(topX, y0, bottomX, y1, level);
55
+ break;
56
+ case 7:
57
+ case 8:
58
+ emit(x0, leftY, topX, y0, level);
59
+ break;
60
+ case 5:
61
+ case 10: {
62
+ const centreAbove = (a + b + c + d) / 4 >= t;
63
+ if (code === 5 === centreAbove) {
64
+ emit(x0, leftY, topX, y0, level);
65
+ emit(bottomX, y1, x1, rightY, level);
66
+ } else {
67
+ emit(topX, y0, x1, rightY, level);
68
+ emit(x0, leftY, bottomX, y1, level);
69
+ }
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ function frac(t, from, to) {
78
+ const d = to - from;
79
+ return d === 0 ? .5 : (t - from) / d;
80
+ }
81
+ export { traceContours };
82
+
83
+ //# sourceMappingURL=contours.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contours.js","names":[],"sources":["../../../src/styles/topo/contours.ts"],"sourcesContent":["export type SegmentSink = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n level: number,\n) => void;\n\n/**\n * Marching squares over a regular grid of samples.\n *\n * `field` holds `cols * rows` samples in row-major order, spaced `cellSize`\n * apart. Contour lines are traced at every multiple of `step`; each segment is\n * passed to `emit` together with its integer level index (threshold / step).\n */\nexport function traceContours(\n field: ArrayLike<number>,\n cols: number,\n rows: number,\n cellSize: number,\n step: number,\n emit: SegmentSink,\n): void {\n if (step <= 0) return;\n\n for (let j = 0; j < rows - 1; j++) {\n const y0 = j * cellSize;\n const y1 = y0 + cellSize;\n for (let i = 0; i < cols - 1; i++) {\n const idx = j * cols + i;\n // a ── b\n // │ │\n // d ── c\n const a = field[idx];\n const b = field[idx + 1];\n const c = field[idx + cols + 1];\n const d = field[idx + cols];\n\n const min = Math.min(a, b, c, d);\n const max = Math.max(a, b, c, d);\n const first = Math.ceil(min / step);\n const last = Math.floor(max / step);\n if (first > last) continue;\n\n const x0 = i * cellSize;\n const x1 = x0 + cellSize;\n\n for (let level = first; level <= last; level++) {\n const t = level * step;\n const code =\n (a >= t ? 8 : 0) | (b >= t ? 4 : 0) | (c >= t ? 2 : 0) | (d >= t ? 1 : 0);\n if (code === 0 || code === 15) continue;\n\n // Crossing points on each edge (only valid when that edge is crossed).\n const topX = x0 + cellSize * frac(t, a, b);\n const rightY = y0 + cellSize * frac(t, b, c);\n const bottomX = x0 + cellSize * frac(t, d, c);\n const leftY = y0 + cellSize * frac(t, a, d);\n\n switch (code) {\n case 1:\n case 14:\n emit(x0, leftY, bottomX, y1, level);\n break;\n case 2:\n case 13:\n emit(bottomX, y1, x1, rightY, level);\n break;\n case 3:\n case 12:\n emit(x0, leftY, x1, rightY, level);\n break;\n case 4:\n case 11:\n emit(topX, y0, x1, rightY, level);\n break;\n case 6:\n case 9:\n emit(topX, y0, bottomX, y1, level);\n break;\n case 7:\n case 8:\n emit(x0, leftY, topX, y0, level);\n break;\n case 5:\n case 10: {\n // Saddle: disambiguate with the cell centre.\n const centreAbove = (a + b + c + d) / 4 >= t;\n const isolateAC = (code === 5) === centreAbove;\n if (isolateAC) {\n emit(x0, leftY, topX, y0, level);\n emit(bottomX, y1, x1, rightY, level);\n } else {\n emit(topX, y0, x1, rightY, level);\n emit(x0, leftY, bottomX, y1, level);\n }\n break;\n }\n }\n }\n }\n }\n}\n\nfunction frac(t: number, from: number, to: number): number {\n const d = to - from;\n return d === 0 ? 0.5 : (t - from) / d;\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,cACd,OACA,MACA,MACA,UACA,MACA,MACM;CACN,IAAI,QAAQ,GAAG;CAEf,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK;EACjC,MAAM,KAAK,IAAI;EACf,MAAM,KAAK,KAAK;EAChB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK;GACjC,MAAM,MAAM,IAAI,OAAO;GAIvB,MAAM,IAAI,MAAM;GAChB,MAAM,IAAI,MAAM,MAAM;GACtB,MAAM,IAAI,MAAM,MAAM,OAAO;GAC7B,MAAM,IAAI,MAAM,MAAM;GAEtB,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;GAC/B,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,GAAG,CAAC;GAC/B,MAAM,QAAQ,KAAK,KAAK,MAAM,IAAI;GAClC,MAAM,OAAO,KAAK,MAAM,MAAM,IAAI;GAClC,IAAI,QAAQ,MAAM;GAElB,MAAM,KAAK,IAAI;GACf,MAAM,KAAK,KAAK;GAEhB,KAAK,IAAI,QAAQ,OAAO,SAAS,MAAM,SAAS;IAC9C,MAAM,IAAI,QAAQ;IAClB,MAAM,QACH,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,IAAI;IACzE,IAAI,SAAS,KAAK,SAAS,IAAI;IAG/B,MAAM,OAAO,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IACzC,MAAM,SAAS,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAC3C,MAAM,UAAU,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAC5C,MAAM,QAAQ,KAAK,WAAW,KAAK,GAAG,GAAG,CAAC;IAE1C,QAAQ,MAAR;KACE,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,SAAS,IAAI,KAAK;MAClC;KACF,KAAK;KACL,KAAK;MACH,KAAK,SAAS,IAAI,IAAI,QAAQ,KAAK;MACnC;KACF,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,IAAI,QAAQ,KAAK;MACjC;KACF,KAAK;KACL,KAAK;MACH,KAAK,MAAM,IAAI,IAAI,QAAQ,KAAK;MAChC;KACF,KAAK;KACL,KAAK;MACH,KAAK,MAAM,IAAI,SAAS,IAAI,KAAK;MACjC;KACF,KAAK;KACL,KAAK;MACH,KAAK,IAAI,OAAO,MAAM,IAAI,KAAK;MAC/B;KACF,KAAK;KACL,KAAK,IAAI;MAEP,MAAM,eAAe,IAAI,IAAI,IAAI,KAAK,KAAK;MAE3C,IADmB,SAAS,MAAO,aACpB;OACb,KAAK,IAAI,OAAO,MAAM,IAAI,KAAK;OAC/B,KAAK,SAAS,IAAI,IAAI,QAAQ,KAAK;MACrC,OAAO;OACL,KAAK,MAAM,IAAI,IAAI,QAAQ,KAAK;OAChC,KAAK,IAAI,OAAO,SAAS,IAAI,KAAK;MACpC;MACA;KACF;IACF;GACF;EACF;CACF;AACF;AAEA,SAAS,KAAK,GAAW,MAAc,IAAoB;CACzD,MAAM,IAAI,KAAK;CACf,OAAO,MAAM,IAAI,MAAO,IAAI,QAAQ;AACtC"}
@@ -0,0 +1,13 @@
1
+ // src/styles/topo/definition.ts
2
+ /**
3
+ * Animated topographic contour lines. The terrain drifts slowly and rises
4
+ * (or, with a negative `pointerStrength`, sinks) under the pointer.
5
+ */
6
+ var topoStyle = {
7
+ name: "topo",
8
+ defaults: require("./options.cjs").topoDefaults,
9
+ animates: (options) => options.speed !== 0
10
+ };
11
+ exports.topoStyle = topoStyle;
12
+
13
+ //# sourceMappingURL=definition.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition.cjs","names":["topoDefaults"],"sources":["../../../src/styles/topo/definition.ts"],"sourcesContent":["import type { StyleBase } from '../../core/style';\nimport { topoDefaults, type TopoOptions } from './options';\n\n/**\n * Animated topographic contour lines. The terrain drifts slowly and rises\n * (or, with a negative `pointerStrength`, sinks) under the pointer.\n */\nexport const topoStyle: StyleBase<TopoOptions> = {\n name: 'topo',\n defaults: topoDefaults,\n animates: (options) => options.speed !== 0,\n};\n"],"mappings":";;;;;AAOA,IAAa,YAAoC;CAC/C,MAAM;CACN,U,uBAAUA,CAAAA,CAAAA;CACV,WAAW,YAAY,QAAQ,UAAU;AAC3C"}
@@ -0,0 +1,7 @@
1
+ import type { StyleBase } from '../../core/style.cjs';
2
+ import { type TopoOptions } from './options.cjs';
3
+ /**
4
+ * Animated topographic contour lines. The terrain drifts slowly and rises
5
+ * (or, with a negative `pointerStrength`, sinks) under the pointer.
6
+ */
7
+ export declare const topoStyle: StyleBase<TopoOptions>;
@@ -0,0 +1,7 @@
1
+ import type { StyleBase } from '../../core/style.js';
2
+ import { type TopoOptions } from './options.js';
3
+ /**
4
+ * Animated topographic contour lines. The terrain drifts slowly and rises
5
+ * (or, with a negative `pointerStrength`, sinks) under the pointer.
6
+ */
7
+ export declare const topoStyle: StyleBase<TopoOptions>;
@@ -0,0 +1,14 @@
1
+ import { topoDefaults } from "./options.js";
2
+ // src/styles/topo/definition.ts
3
+ /**
4
+ * Animated topographic contour lines. The terrain drifts slowly and rises
5
+ * (or, with a negative `pointerStrength`, sinks) under the pointer.
6
+ */
7
+ var topoStyle = {
8
+ name: "topo",
9
+ defaults: topoDefaults,
10
+ animates: (options) => options.speed !== 0
11
+ };
12
+ export { topoStyle };
13
+
14
+ //# sourceMappingURL=definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition.js","names":[],"sources":["../../../src/styles/topo/definition.ts"],"sourcesContent":["import type { StyleBase } from '../../core/style';\nimport { topoDefaults, type TopoOptions } from './options';\n\n/**\n * Animated topographic contour lines. The terrain drifts slowly and rises\n * (or, with a negative `pointerStrength`, sinks) under the pointer.\n */\nexport const topoStyle: StyleBase<TopoOptions> = {\n name: 'topo',\n defaults: topoDefaults,\n animates: (options) => options.speed !== 0,\n};\n"],"mappings":";;;;;;AAOA,IAAa,YAAoC;CAC/C,MAAM;CACN,UAAU;CACV,WAAW,YAAY,QAAQ,UAAU;AAC3C"}
@@ -0,0 +1,118 @@
1
+ const require_noise = require("../../shared/noise.cjs");
2
+ // src/styles/topo/field.ts
3
+ /** Noise-time distance between sampled keyframes; frames in between are blended. */
4
+ var KEY_DT = .02;
5
+ /**
6
+ * The terrain height field, sampled on a grid `cellSize` pixels apart.
7
+ *
8
+ * Sampling noise for every grid point is the most expensive step, but the
9
+ * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart
10
+ * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.
11
+ * The keyframe after B is built a few rows per frame to avoid spikes.
12
+ */
13
+ function createKeyframeField(initial) {
14
+ let params = initial;
15
+ let noise = require_noise.createNoise3D(params.seed);
16
+ let norm = 2 - 2 ** (1 - params.octaves);
17
+ let width = 0;
18
+ let height = 0;
19
+ let cols = 0;
20
+ let rows = 0;
21
+ let keyA = /* @__PURE__ */ new Float32Array(0);
22
+ let keyB = /* @__PURE__ */ new Float32Array(0);
23
+ let keyNext = /* @__PURE__ */ new Float32Array(0);
24
+ let keyTime = 0;
25
+ let keyNextRows = 0;
26
+ let valid = false;
27
+ let version = 0;
28
+ function allocate() {
29
+ const nextCols = Math.ceil(width / params.cellSize) + 1;
30
+ const nextRows = Math.ceil(height / params.cellSize) + 1;
31
+ if (nextCols === cols && nextRows === rows) return;
32
+ cols = nextCols;
33
+ rows = nextRows;
34
+ keyA = new Float32Array(cols * rows);
35
+ keyB = new Float32Array(cols * rows);
36
+ keyNext = new Float32Array(cols * rows);
37
+ valid = false;
38
+ }
39
+ function sampleRows(target, t, fromRow, toRow) {
40
+ const { cellSize, octaves, scale } = params;
41
+ for (let j = fromRow; j < toRow; j++) {
42
+ const y = j * cellSize;
43
+ for (let i = 0; i < cols; i++) {
44
+ const x = i * cellSize;
45
+ let value = 0;
46
+ for (let o = 0, amp = 1, freq = scale; o < octaves; o++, amp *= .5, freq *= 2) value += amp * noise(x * freq, y * freq, t + o * 17.3);
47
+ target[j * cols + i] = value / norm;
48
+ }
49
+ }
50
+ }
51
+ return {
52
+ get cols() {
53
+ return cols;
54
+ },
55
+ get rows() {
56
+ return rows;
57
+ },
58
+ get keyA() {
59
+ return keyA;
60
+ },
61
+ get keyB() {
62
+ return keyB;
63
+ },
64
+ get version() {
65
+ return version;
66
+ },
67
+ configure(next) {
68
+ const prev = params;
69
+ if (next.seed === prev.seed && next.scale === prev.scale && next.octaves === prev.octaves && next.cellSize === prev.cellSize) return;
70
+ params = {
71
+ seed: next.seed,
72
+ scale: next.scale,
73
+ octaves: next.octaves,
74
+ cellSize: next.cellSize
75
+ };
76
+ if (next.seed !== prev.seed) noise = require_noise.createNoise3D(next.seed);
77
+ norm = 2 - 2 ** (1 - next.octaves);
78
+ allocate();
79
+ valid = false;
80
+ },
81
+ resize(nextWidth, nextHeight) {
82
+ width = nextWidth;
83
+ height = nextHeight;
84
+ allocate();
85
+ },
86
+ advance(time) {
87
+ if (!valid || time < keyTime || time >= keyTime + 2 * KEY_DT) {
88
+ keyTime = time;
89
+ sampleRows(keyA, keyTime, 0, rows);
90
+ sampleRows(keyB, keyTime + KEY_DT, 0, rows);
91
+ keyNextRows = 0;
92
+ valid = true;
93
+ version++;
94
+ }
95
+ if (time >= keyTime + KEY_DT) {
96
+ sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, rows);
97
+ [keyA, keyB, keyNext] = [
98
+ keyB,
99
+ keyNext,
100
+ keyA
101
+ ];
102
+ keyTime += KEY_DT;
103
+ keyNextRows = 0;
104
+ version++;
105
+ }
106
+ const progress = (time - keyTime) / KEY_DT;
107
+ const wanted = Math.min(rows, Math.ceil(rows * progress / .8));
108
+ if (wanted > keyNextRows) {
109
+ sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, wanted);
110
+ keyNextRows = wanted;
111
+ }
112
+ return progress;
113
+ }
114
+ };
115
+ }
116
+ exports.createKeyframeField = createKeyframeField;
117
+
118
+ //# sourceMappingURL=field.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.cjs","names":["createNoise3D"],"sources":["../../../src/styles/topo/field.ts"],"sourcesContent":["import { createNoise3D, type Noise3D } from '../../shared/noise';\nimport type { ResolvedTopoOptions } from './options';\n\n/** Noise-time distance between sampled keyframes; frames in between are blended. */\nconst KEY_DT = 0.02;\n\nexport type FieldParams = Pick<ResolvedTopoOptions, 'seed' | 'scale' | 'octaves' | 'cellSize'>;\n\nexport interface KeyframeField {\n readonly cols: number;\n readonly rows: number;\n /** The terrain at time `t` is `keyA + (keyB - keyA) * blend`, see `advance()`. */\n readonly keyA: Float32Array;\n readonly keyB: Float32Array;\n /** Changes whenever the contents of `keyA` / `keyB` change. */\n readonly version: number;\n /** Apply new parameters; resamples only if something actually changed. */\n configure(params: FieldParams): void;\n /** Size of the area to cover, in CSS pixels. */\n resize(width: number, height: number): void;\n /** Bring the keyframes up to `time` and return the blend factor between them. */\n advance(time: number): number;\n}\n\n/**\n * The terrain height field, sampled on a grid `cellSize` pixels apart.\n *\n * Sampling noise for every grid point is the most expensive step, but the\n * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart\n * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.\n * The keyframe after B is built a few rows per frame to avoid spikes.\n */\nexport function createKeyframeField(initial: FieldParams): KeyframeField {\n let params = initial;\n let noise: Noise3D = createNoise3D(params.seed);\n // Sum of octave amplitudes (1 + 1/2 + 1/4 + …), to normalise the result to [-1, 1].\n let norm = 2 - 2 ** (1 - params.octaves);\n\n let width = 0;\n let height = 0;\n let cols = 0;\n let rows = 0;\n let keyA = new Float32Array(0);\n let keyB = new Float32Array(0);\n let keyNext = new Float32Array(0);\n let keyTime = 0;\n let keyNextRows = 0;\n let valid = false;\n let version = 0;\n\n function allocate(): void {\n const nextCols = Math.ceil(width / params.cellSize) + 1;\n const nextRows = Math.ceil(height / params.cellSize) + 1;\n if (nextCols === cols && nextRows === rows) return;\n cols = nextCols;\n rows = nextRows;\n keyA = new Float32Array(cols * rows);\n keyB = new Float32Array(cols * rows);\n keyNext = new Float32Array(cols * rows);\n valid = false;\n }\n\n function sampleRows(target: Float32Array, t: number, fromRow: number, toRow: number): void {\n const { cellSize, octaves, scale } = params;\n for (let j = fromRow; j < toRow; j++) {\n const y = j * cellSize;\n for (let i = 0; i < cols; i++) {\n const x = i * cellSize;\n let value = 0;\n for (let o = 0, amp = 1, freq = scale; o < octaves; o++, amp *= 0.5, freq *= 2) {\n value += amp * noise(x * freq, y * freq, t + o * 17.3);\n }\n target[j * cols + i] = value / norm;\n }\n }\n }\n\n return {\n get cols() {\n return cols;\n },\n get rows() {\n return rows;\n },\n get keyA() {\n return keyA;\n },\n get keyB() {\n return keyB;\n },\n get version() {\n return version;\n },\n\n configure(next) {\n const prev = params;\n if (\n next.seed === prev.seed &&\n next.scale === prev.scale &&\n next.octaves === prev.octaves &&\n next.cellSize === prev.cellSize\n ) {\n return;\n }\n params = { seed: next.seed, scale: next.scale, octaves: next.octaves, cellSize: next.cellSize };\n if (next.seed !== prev.seed) noise = createNoise3D(next.seed);\n norm = 2 - 2 ** (1 - next.octaves);\n allocate();\n valid = false;\n },\n\n resize(nextWidth, nextHeight) {\n width = nextWidth;\n height = nextHeight;\n allocate();\n },\n\n advance(time) {\n if (!valid || time < keyTime || time >= keyTime + 2 * KEY_DT) {\n keyTime = time;\n sampleRows(keyA, keyTime, 0, rows);\n sampleRows(keyB, keyTime + KEY_DT, 0, rows);\n keyNextRows = 0;\n valid = true;\n version++;\n }\n if (time >= keyTime + KEY_DT) {\n sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, rows);\n [keyA, keyB, keyNext] = [keyB, keyNext, keyA];\n keyTime += KEY_DT;\n keyNextRows = 0;\n version++;\n }\n // Spread the next keyframe over the first 80% of the interval.\n const progress = (time - keyTime) / KEY_DT;\n const wanted = Math.min(rows, Math.ceil((rows * progress) / 0.8));\n if (wanted > keyNextRows) {\n sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, wanted);\n keyNextRows = wanted;\n }\n return progress;\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { ResolvedTopoOptions } from './options.cjs';
2
+ export type FieldParams = Pick<ResolvedTopoOptions, 'seed' | 'scale' | 'octaves' | 'cellSize'>;
3
+ export interface KeyframeField {
4
+ readonly cols: number;
5
+ readonly rows: number;
6
+ /** The terrain at time `t` is `keyA + (keyB - keyA) * blend`, see `advance()`. */
7
+ readonly keyA: Float32Array;
8
+ readonly keyB: Float32Array;
9
+ /** Changes whenever the contents of `keyA` / `keyB` change. */
10
+ readonly version: number;
11
+ /** Apply new parameters; resamples only if something actually changed. */
12
+ configure(params: FieldParams): void;
13
+ /** Size of the area to cover, in CSS pixels. */
14
+ resize(width: number, height: number): void;
15
+ /** Bring the keyframes up to `time` and return the blend factor between them. */
16
+ advance(time: number): number;
17
+ }
18
+ /**
19
+ * The terrain height field, sampled on a grid `cellSize` pixels apart.
20
+ *
21
+ * Sampling noise for every grid point is the most expensive step, but the
22
+ * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart
23
+ * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.
24
+ * The keyframe after B is built a few rows per frame to avoid spikes.
25
+ */
26
+ export declare function createKeyframeField(initial: FieldParams): KeyframeField;
@@ -0,0 +1,26 @@
1
+ import type { ResolvedTopoOptions } from './options.js';
2
+ export type FieldParams = Pick<ResolvedTopoOptions, 'seed' | 'scale' | 'octaves' | 'cellSize'>;
3
+ export interface KeyframeField {
4
+ readonly cols: number;
5
+ readonly rows: number;
6
+ /** The terrain at time `t` is `keyA + (keyB - keyA) * blend`, see `advance()`. */
7
+ readonly keyA: Float32Array;
8
+ readonly keyB: Float32Array;
9
+ /** Changes whenever the contents of `keyA` / `keyB` change. */
10
+ readonly version: number;
11
+ /** Apply new parameters; resamples only if something actually changed. */
12
+ configure(params: FieldParams): void;
13
+ /** Size of the area to cover, in CSS pixels. */
14
+ resize(width: number, height: number): void;
15
+ /** Bring the keyframes up to `time` and return the blend factor between them. */
16
+ advance(time: number): number;
17
+ }
18
+ /**
19
+ * The terrain height field, sampled on a grid `cellSize` pixels apart.
20
+ *
21
+ * Sampling noise for every grid point is the most expensive step, but the
22
+ * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart
23
+ * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.
24
+ * The keyframe after B is built a few rows per frame to avoid spikes.
25
+ */
26
+ export declare function createKeyframeField(initial: FieldParams): KeyframeField;
@@ -0,0 +1,118 @@
1
+ import { createNoise3D } from "../../shared/noise.js";
2
+ // src/styles/topo/field.ts
3
+ /** Noise-time distance between sampled keyframes; frames in between are blended. */
4
+ var KEY_DT = .02;
5
+ /**
6
+ * The terrain height field, sampled on a grid `cellSize` pixels apart.
7
+ *
8
+ * Sampling noise for every grid point is the most expensive step, but the
9
+ * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart
10
+ * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.
11
+ * The keyframe after B is built a few rows per frame to avoid spikes.
12
+ */
13
+ function createKeyframeField(initial) {
14
+ let params = initial;
15
+ let noise = createNoise3D(params.seed);
16
+ let norm = 2 - 2 ** (1 - params.octaves);
17
+ let width = 0;
18
+ let height = 0;
19
+ let cols = 0;
20
+ let rows = 0;
21
+ let keyA = /* @__PURE__ */ new Float32Array(0);
22
+ let keyB = /* @__PURE__ */ new Float32Array(0);
23
+ let keyNext = /* @__PURE__ */ new Float32Array(0);
24
+ let keyTime = 0;
25
+ let keyNextRows = 0;
26
+ let valid = false;
27
+ let version = 0;
28
+ function allocate() {
29
+ const nextCols = Math.ceil(width / params.cellSize) + 1;
30
+ const nextRows = Math.ceil(height / params.cellSize) + 1;
31
+ if (nextCols === cols && nextRows === rows) return;
32
+ cols = nextCols;
33
+ rows = nextRows;
34
+ keyA = new Float32Array(cols * rows);
35
+ keyB = new Float32Array(cols * rows);
36
+ keyNext = new Float32Array(cols * rows);
37
+ valid = false;
38
+ }
39
+ function sampleRows(target, t, fromRow, toRow) {
40
+ const { cellSize, octaves, scale } = params;
41
+ for (let j = fromRow; j < toRow; j++) {
42
+ const y = j * cellSize;
43
+ for (let i = 0; i < cols; i++) {
44
+ const x = i * cellSize;
45
+ let value = 0;
46
+ for (let o = 0, amp = 1, freq = scale; o < octaves; o++, amp *= .5, freq *= 2) value += amp * noise(x * freq, y * freq, t + o * 17.3);
47
+ target[j * cols + i] = value / norm;
48
+ }
49
+ }
50
+ }
51
+ return {
52
+ get cols() {
53
+ return cols;
54
+ },
55
+ get rows() {
56
+ return rows;
57
+ },
58
+ get keyA() {
59
+ return keyA;
60
+ },
61
+ get keyB() {
62
+ return keyB;
63
+ },
64
+ get version() {
65
+ return version;
66
+ },
67
+ configure(next) {
68
+ const prev = params;
69
+ if (next.seed === prev.seed && next.scale === prev.scale && next.octaves === prev.octaves && next.cellSize === prev.cellSize) return;
70
+ params = {
71
+ seed: next.seed,
72
+ scale: next.scale,
73
+ octaves: next.octaves,
74
+ cellSize: next.cellSize
75
+ };
76
+ if (next.seed !== prev.seed) noise = createNoise3D(next.seed);
77
+ norm = 2 - 2 ** (1 - next.octaves);
78
+ allocate();
79
+ valid = false;
80
+ },
81
+ resize(nextWidth, nextHeight) {
82
+ width = nextWidth;
83
+ height = nextHeight;
84
+ allocate();
85
+ },
86
+ advance(time) {
87
+ if (!valid || time < keyTime || time >= keyTime + 2 * KEY_DT) {
88
+ keyTime = time;
89
+ sampleRows(keyA, keyTime, 0, rows);
90
+ sampleRows(keyB, keyTime + KEY_DT, 0, rows);
91
+ keyNextRows = 0;
92
+ valid = true;
93
+ version++;
94
+ }
95
+ if (time >= keyTime + KEY_DT) {
96
+ sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, rows);
97
+ [keyA, keyB, keyNext] = [
98
+ keyB,
99
+ keyNext,
100
+ keyA
101
+ ];
102
+ keyTime += KEY_DT;
103
+ keyNextRows = 0;
104
+ version++;
105
+ }
106
+ const progress = (time - keyTime) / KEY_DT;
107
+ const wanted = Math.min(rows, Math.ceil(rows * progress / .8));
108
+ if (wanted > keyNextRows) {
109
+ sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, wanted);
110
+ keyNextRows = wanted;
111
+ }
112
+ return progress;
113
+ }
114
+ };
115
+ }
116
+ export { createKeyframeField };
117
+
118
+ //# sourceMappingURL=field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field.js","names":[],"sources":["../../../src/styles/topo/field.ts"],"sourcesContent":["import { createNoise3D, type Noise3D } from '../../shared/noise';\nimport type { ResolvedTopoOptions } from './options';\n\n/** Noise-time distance between sampled keyframes; frames in between are blended. */\nconst KEY_DT = 0.02;\n\nexport type FieldParams = Pick<ResolvedTopoOptions, 'seed' | 'scale' | 'octaves' | 'cellSize'>;\n\nexport interface KeyframeField {\n readonly cols: number;\n readonly rows: number;\n /** The terrain at time `t` is `keyA + (keyB - keyA) * blend`, see `advance()`. */\n readonly keyA: Float32Array;\n readonly keyB: Float32Array;\n /** Changes whenever the contents of `keyA` / `keyB` change. */\n readonly version: number;\n /** Apply new parameters; resamples only if something actually changed. */\n configure(params: FieldParams): void;\n /** Size of the area to cover, in CSS pixels. */\n resize(width: number, height: number): void;\n /** Bring the keyframes up to `time` and return the blend factor between them. */\n advance(time: number): number;\n}\n\n/**\n * The terrain height field, sampled on a grid `cellSize` pixels apart.\n *\n * Sampling noise for every grid point is the most expensive step, but the\n * terrain changes slowly. So noise is only sampled at keyframes KEY_DT apart\n * (A at `keyTime`, B at `keyTime + KEY_DT`) and every frame blends between them.\n * The keyframe after B is built a few rows per frame to avoid spikes.\n */\nexport function createKeyframeField(initial: FieldParams): KeyframeField {\n let params = initial;\n let noise: Noise3D = createNoise3D(params.seed);\n // Sum of octave amplitudes (1 + 1/2 + 1/4 + …), to normalise the result to [-1, 1].\n let norm = 2 - 2 ** (1 - params.octaves);\n\n let width = 0;\n let height = 0;\n let cols = 0;\n let rows = 0;\n let keyA = new Float32Array(0);\n let keyB = new Float32Array(0);\n let keyNext = new Float32Array(0);\n let keyTime = 0;\n let keyNextRows = 0;\n let valid = false;\n let version = 0;\n\n function allocate(): void {\n const nextCols = Math.ceil(width / params.cellSize) + 1;\n const nextRows = Math.ceil(height / params.cellSize) + 1;\n if (nextCols === cols && nextRows === rows) return;\n cols = nextCols;\n rows = nextRows;\n keyA = new Float32Array(cols * rows);\n keyB = new Float32Array(cols * rows);\n keyNext = new Float32Array(cols * rows);\n valid = false;\n }\n\n function sampleRows(target: Float32Array, t: number, fromRow: number, toRow: number): void {\n const { cellSize, octaves, scale } = params;\n for (let j = fromRow; j < toRow; j++) {\n const y = j * cellSize;\n for (let i = 0; i < cols; i++) {\n const x = i * cellSize;\n let value = 0;\n for (let o = 0, amp = 1, freq = scale; o < octaves; o++, amp *= 0.5, freq *= 2) {\n value += amp * noise(x * freq, y * freq, t + o * 17.3);\n }\n target[j * cols + i] = value / norm;\n }\n }\n }\n\n return {\n get cols() {\n return cols;\n },\n get rows() {\n return rows;\n },\n get keyA() {\n return keyA;\n },\n get keyB() {\n return keyB;\n },\n get version() {\n return version;\n },\n\n configure(next) {\n const prev = params;\n if (\n next.seed === prev.seed &&\n next.scale === prev.scale &&\n next.octaves === prev.octaves &&\n next.cellSize === prev.cellSize\n ) {\n return;\n }\n params = { seed: next.seed, scale: next.scale, octaves: next.octaves, cellSize: next.cellSize };\n if (next.seed !== prev.seed) noise = createNoise3D(next.seed);\n norm = 2 - 2 ** (1 - next.octaves);\n allocate();\n valid = false;\n },\n\n resize(nextWidth, nextHeight) {\n width = nextWidth;\n height = nextHeight;\n allocate();\n },\n\n advance(time) {\n if (!valid || time < keyTime || time >= keyTime + 2 * KEY_DT) {\n keyTime = time;\n sampleRows(keyA, keyTime, 0, rows);\n sampleRows(keyB, keyTime + KEY_DT, 0, rows);\n keyNextRows = 0;\n valid = true;\n version++;\n }\n if (time >= keyTime + KEY_DT) {\n sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, rows);\n [keyA, keyB, keyNext] = [keyB, keyNext, keyA];\n keyTime += KEY_DT;\n keyNextRows = 0;\n version++;\n }\n // Spread the next keyframe over the first 80% of the interval.\n const progress = (time - keyTime) / KEY_DT;\n const wanted = Math.min(rows, Math.ceil((rows * progress) / 0.8));\n if (wanted > keyNextRows) {\n sampleRows(keyNext, keyTime + 2 * KEY_DT, keyNextRows, wanted);\n keyNextRows = wanted;\n }\n return progress;\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ // src/styles/topo/options.ts
2
+ var topoDefaults = Object.freeze({
3
+ lineColor: "#5b6576",
4
+ majorLineColor: "#7dd3a8",
5
+ lineOpacity: .5,
6
+ lineWidth: 1,
7
+ majorLineWidth: 1.75,
8
+ majorEvery: 5,
9
+ levels: 12,
10
+ scale: .0025,
11
+ octaves: 2,
12
+ speed: .025,
13
+ resolution: 6,
14
+ seed: 1332056948,
15
+ pointerRadius: 100,
16
+ pointerStrength: .35
17
+ });
18
+ function resolveTopoOptions(options) {
19
+ return {
20
+ lineColor: options.lineColor,
21
+ majorLineColor: options.majorLineColor ?? options.lineColor,
22
+ lineOpacity: Math.min(1, Math.max(0, options.lineOpacity)),
23
+ lineWidth: Math.max(.1, options.lineWidth),
24
+ majorLineWidth: Math.max(.1, options.majorLineWidth),
25
+ majorEvery: Math.max(0, Math.round(options.majorEvery)),
26
+ levelStep: 2 / Math.max(1, options.levels),
27
+ cellSize: Math.max(2, options.resolution),
28
+ octaves: Math.max(1, Math.round(options.octaves)),
29
+ scale: options.scale,
30
+ speed: Math.abs(options.speed),
31
+ seed: options.seed,
32
+ pointerRadius: Math.max(1, options.pointerRadius),
33
+ pointerStrength: options.pointerStrength
34
+ };
35
+ }
36
+ exports.resolveTopoOptions = resolveTopoOptions;
37
+ exports.topoDefaults = topoDefaults;
38
+
39
+ //# sourceMappingURL=options.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.cjs","names":[],"sources":["../../../src/styles/topo/options.ts"],"sourcesContent":["export interface TopoOptions {\n /** Stroke colour of regular contour lines. Any CSS colour. */\n lineColor: string;\n /** Stroke colour of every `majorEvery`-th (\"index\") line. Defaults to `lineColor`. */\n majorLineColor?: string;\n /** Opacity of all lines, from `0` (invisible) to `1` (opaque). Multiplies any alpha in the colours. */\n lineOpacity: number;\n /** Width of regular lines, in CSS pixels. */\n lineWidth: number;\n /** Width of index lines, in CSS pixels. */\n majorLineWidth: number;\n /** Every n-th contour is drawn as an index line. `0` disables index lines. */\n majorEvery: number;\n /** Number of contour levels across the full elevation range. More = denser lines. */\n levels: number;\n /** Noise frequency per CSS pixel. Smaller = larger, smoother landforms. */\n scale: number;\n /** Noise octaves. More = more detailed, rougher terrain (and more CPU). */\n octaves: number;\n /** How fast the terrain morphs, in noise units per second. `0` = static. */\n speed: number;\n /** Size of a sampling cell in CSS pixels. Smaller = smoother lines, more CPU. */\n resolution: number;\n /** Seed for the terrain. Same seed, same landscape. Pass a random number for a different one on every load. */\n seed: number;\n /** Radius of the pointer's influence, in CSS pixels. */\n pointerRadius: number;\n /** Height of the bump under the pointer. Negative values dig a crater. */\n pointerStrength: number;\n}\n\nexport const topoDefaults: Readonly<TopoOptions> = Object.freeze({\n lineColor: '#5b6576',\n majorLineColor: '#7dd3a8',\n lineOpacity: 0.5,\n lineWidth: 1,\n majorLineWidth: 1.75,\n majorEvery: 5,\n levels: 12,\n scale: 0.0025,\n octaves: 2,\n speed: 0.025,\n resolution: 6,\n seed: 1332056948,\n pointerRadius: 100,\n pointerStrength: 0.35,\n});\n\n/** Options after clamping and deriving: what the field and the renderers consume. */\nexport interface ResolvedTopoOptions {\n lineColor: string;\n majorLineColor: string;\n lineOpacity: number;\n lineWidth: number;\n majorLineWidth: number;\n /** Integer; `0` = no index lines. */\n majorEvery: number;\n /** Height difference between neighbouring contour levels. */\n levelStep: number;\n /** Grid spacing of the height field, in CSS pixels. */\n cellSize: number;\n octaves: number;\n scale: number;\n speed: number;\n seed: number;\n pointerRadius: number;\n pointerStrength: number;\n}\n\nexport function resolveTopoOptions(options: TopoOptions): ResolvedTopoOptions {\n return {\n lineColor: options.lineColor,\n majorLineColor: options.majorLineColor ?? options.lineColor,\n lineOpacity: Math.min(1, Math.max(0, options.lineOpacity)),\n lineWidth: Math.max(0.1, options.lineWidth),\n majorLineWidth: Math.max(0.1, options.majorLineWidth),\n majorEvery: Math.max(0, Math.round(options.majorEvery)),\n // The height field spans roughly [-1, 1], so the levels cover a range of 2.\n levelStep: 2 / Math.max(1, options.levels),\n cellSize: Math.max(2, options.resolution),\n octaves: Math.max(1, Math.round(options.octaves)),\n scale: options.scale,\n // The keyframes only step forwards in time; morphing backwards looks the same, so use the magnitude.\n speed: Math.abs(options.speed),\n seed: options.seed,\n pointerRadius: Math.max(1, options.pointerRadius),\n pointerStrength: options.pointerStrength,\n };\n}\n"],"mappings":";AA+BA,IAAa,eAAsC,OAAO,OAAO;CAC/D,WAAW;CACX,gBAAgB;CAChB,aAAa;CACb,WAAW;CACX,gBAAgB;CAChB,YAAY;CACZ,QAAQ;CACR,OAAO;CACP,SAAS;CACT,OAAO;CACP,YAAY;CACZ,MAAM;CACN,eAAe;CACf,iBAAiB;AACnB,CAAC;AAuBD,SAAgB,mBAAmB,SAA2C;CAC5E,OAAO;EACL,WAAW,QAAQ;EACnB,gBAAgB,QAAQ,kBAAkB,QAAQ;EAClD,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,WAAW,CAAC;EACzD,WAAW,KAAK,IAAI,IAAK,QAAQ,SAAS;EAC1C,gBAAgB,KAAK,IAAI,IAAK,QAAQ,cAAc;EACpD,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,UAAU,CAAC;EAEtD,WAAW,IAAI,KAAK,IAAI,GAAG,QAAQ,MAAM;EACzC,UAAU,KAAK,IAAI,GAAG,QAAQ,UAAU;EACxC,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,QAAQ,OAAO,CAAC;EAChD,OAAO,QAAQ;EAEf,OAAO,KAAK,IAAI,QAAQ,KAAK;EAC7B,MAAM,QAAQ;EACd,eAAe,KAAK,IAAI,GAAG,QAAQ,aAAa;EAChD,iBAAiB,QAAQ;CAC3B;AACF"}