@pirireis/webglobeplugins 0.17.1 → 1.0.2

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 (272) hide show
  1. package/Math/{angle-calculation.js → angle-calculation.ts} +18 -14
  2. package/Math/{arc-cdf-points.js → arc-cdf-points.ts} +329 -272
  3. package/Math/{arc-generate-points-exponantial.js → arc-generate-points-exponantial.ts} +299 -254
  4. package/Math/{arc.js → arc.ts} +421 -292
  5. package/Math/bounds/line-bbox.js +225 -186
  6. package/Math/{circle-cdf-points.js → circle-cdf-points.ts} +143 -78
  7. package/Math/{circle.js → circle.ts} +49 -33
  8. package/Math/{constants.js → constants.ts} +12 -4
  9. package/Math/contour/{quadtreecontours.js → quadtreecontours.ts} +371 -300
  10. package/Math/contour/quadtreecontours1.js +336 -298
  11. package/Math/{finite-line-2d.js → finite-line-2d.ts} +68 -58
  12. package/Math/haversine.ts +33 -0
  13. package/Math/index.js +0 -1
  14. package/Math/juction/{arc-plane.js → arc-plane.ts} +203 -143
  15. package/Math/juction/{line-sphere.js → line-sphere.ts} +32 -22
  16. package/Math/juction/{plane-plane.js → plane-plane.ts} +62 -53
  17. package/Math/{line.js → line.ts} +84 -52
  18. package/Math/matrix4.ts +0 -0
  19. package/Math/mesh/mapbox-delaunay.d.ts +74 -0
  20. package/Math/{methods.js → methods.ts} +182 -113
  21. package/Math/{plane.js → plane.ts} +92 -56
  22. package/Math/{quaternion.js → quaternion.ts} +128 -106
  23. package/Math/roadmap.md +10 -0
  24. package/Math/templete-shapes/{grid-visually-equal.js → grid-visually-equal.ts} +118 -65
  25. package/Math/tessellation/constants.ts +1 -0
  26. package/Math/tessellation/methods.ts +79 -0
  27. package/Math/tessellation/nearest-value-padding.ts +147 -0
  28. package/Math/tessellation/roadmap.md +48 -0
  29. package/Math/tessellation/spherical-triangle-area.ts +127 -0
  30. package/Math/tessellation/tile-merger.ts +578 -0
  31. package/Math/tessellation/triangle-tessellation.ts +533 -0
  32. package/Math/tessellation/types.ts +1 -0
  33. package/Math/types.ts +68 -0
  34. package/Math/utils.js +3 -2
  35. package/Math/{vec3.js → vec3.ts} +227 -151
  36. package/Math/xyz-tile.ts +26 -0
  37. package/algorithms/search-binary.js +14 -16
  38. package/altitude-locator/adaptors.js +0 -1
  39. package/altitude-locator/keymethod.js +0 -1
  40. package/altitude-locator/plugin.js +445 -345
  41. package/altitude-locator/types.js +26 -21
  42. package/compass-rose/compass-rose-padding-flat.js +274 -230
  43. package/compass-rose/{compass-text-writer.js → compass-text-writer.ts} +210 -155
  44. package/compass-rose/index.js +3 -3
  45. package/{constants.js → constants.ts} +8 -6
  46. package/heatwave/datamanager.js +168 -149
  47. package/heatwave/heatwave.js +261 -206
  48. package/heatwave/index.js +5 -5
  49. package/heatwave/isobar.js +340 -303
  50. package/heatwave/{texture-point-sampler.js → texture-point-sampler.ts} +220 -187
  51. package/investigation-tools/draw/tiles/adapters.ts +133 -0
  52. package/investigation-tools/draw/tiles/{tiles.js → tiles.ts} +162 -128
  53. package/jest.config.js +6 -7
  54. package/package.json +1 -1
  55. package/pin/pin-object-array1.js +381 -300
  56. package/pin/pin-point-totem1.js +77 -60
  57. package/programs/arrowfield/arrow-field.js +89 -60
  58. package/programs/arrowfield/logic.js +173 -141
  59. package/programs/data2legend/density-to-legend.js +86 -68
  60. package/programs/data2legend/point-to-density-texture.js +84 -67
  61. package/programs/float2legendwithratio/index.js +3 -2
  62. package/programs/float2legendwithratio/logic.js +144 -118
  63. package/programs/float2legendwithratio/object.js +141 -104
  64. package/programs/helpers/blender.js +73 -58
  65. package/programs/helpers/{fadeaway.js → fadeaway.ts} +73 -55
  66. package/programs/index.js +19 -20
  67. package/programs/line-on-globe/circle-accurate-3d.js +112 -85
  68. package/programs/line-on-globe/circle-accurate-flat.js +200 -148
  69. package/programs/line-on-globe/degree-padding-around-circle-3d.js +134 -102
  70. package/programs/line-on-globe/index.js +0 -1
  71. package/programs/line-on-globe/lines-color-instanced-flat.js +99 -80
  72. package/programs/line-on-globe/linestrip/data.ts +29 -0
  73. package/programs/line-on-globe/linestrip/{linestrip.js → linestrip.ts} +152 -93
  74. package/programs/line-on-globe/{naive-accurate-flexible.js → naive-accurate-flexible.ts} +175 -126
  75. package/programs/line-on-globe/util.js +8 -5
  76. package/programs/picking/pickable-polygon-renderer.js +129 -98
  77. package/programs/picking/pickable-renderer.js +130 -98
  78. package/programs/point-on-globe/element-globe-surface-glow.js +122 -93
  79. package/programs/point-on-globe/element-point-glow.js +114 -80
  80. package/programs/point-on-globe/square-pixel-point.js +139 -120
  81. package/programs/polygon-on-globe/roadmap.md +8 -0
  82. package/programs/polygon-on-globe/texture-dem-triangles.ts +290 -0
  83. package/programs/{programcache.js → programcache.ts} +134 -126
  84. package/programs/rings/index.js +1 -1
  85. package/programs/rings/partial-ring/{piece-of-pie.js → piece-of-pie.ts} +222 -152
  86. package/programs/totems/camera-totem-attactment-interface.ts +4 -0
  87. package/programs/totems/{camerauniformblock.js → camerauniformblock.ts} +326 -230
  88. package/programs/totems/{canvas-webglobe-info.js → canvas-webglobe-info.ts} +147 -132
  89. package/programs/totems/dem-textures-manager.ts +368 -0
  90. package/programs/totems/{globe-changes.js → globe-changes.ts} +79 -59
  91. package/programs/totems/gpu-selection-uniform-block.js +127 -99
  92. package/programs/totems/{index.js → index.ts} +2 -2
  93. package/programs/two-d/pixel-padding-for-compass.js +101 -87
  94. package/programs/util.js +19 -14
  95. package/programs/vectorfields/logics/{constants.js → constants.ts} +5 -4
  96. package/programs/vectorfields/logics/drawrectangleparticles.ts +182 -0
  97. package/programs/vectorfields/logics/index.js +4 -2
  98. package/programs/vectorfields/logics/particle-ubo.ts +23 -0
  99. package/programs/vectorfields/logics/{pixelbased.js → pixelbased.ts} +119 -84
  100. package/programs/vectorfields/logics/ubo.js +57 -51
  101. package/programs/vectorfields/{pingpongbuffermanager.js → pingpongbuffermanager.ts} +113 -73
  102. package/publish.bat +62 -0
  103. package/range-tools-on-terrain/bearing-line/{adapters.js → adapters.ts} +154 -114
  104. package/range-tools-on-terrain/bearing-line/{plugin.js → plugin.ts} +569 -457
  105. package/range-tools-on-terrain/bearing-line/types.ts +65 -0
  106. package/range-tools-on-terrain/circle-line-chain/{adapters.js → adapters.ts} +104 -85
  107. package/range-tools-on-terrain/circle-line-chain/{chain-list-map.js → chain-list-map.ts} +446 -382
  108. package/range-tools-on-terrain/circle-line-chain/{plugin.js → plugin.ts} +607 -464
  109. package/range-tools-on-terrain/circle-line-chain/types.ts +43 -0
  110. package/range-tools-on-terrain/range-ring/{adapters.js → adapters.ts} +114 -93
  111. package/range-tools-on-terrain/range-ring/{enum.js → enum.ts} +2 -2
  112. package/range-tools-on-terrain/range-ring/{plugin.js → plugin.ts} +444 -377
  113. package/range-tools-on-terrain/range-ring/rangeringangletext.ts +396 -0
  114. package/range-tools-on-terrain/range-ring/types.ts +30 -0
  115. package/semiplugins/interface.ts +14 -0
  116. package/semiplugins/lightweight/{line-plugin.js → line-plugin.ts} +342 -221
  117. package/semiplugins/lightweight/{piece-of-pie-plugin.js → piece-of-pie-plugin.ts} +275 -200
  118. package/semiplugins/shape-on-terrain/{arc-plugin.js → arc-plugin.ts} +616 -481
  119. package/semiplugins/shape-on-terrain/{circle-plugin.js → circle-plugin.ts} +588 -444
  120. package/semiplugins/shape-on-terrain/goal.md +12 -0
  121. package/semiplugins/shape-on-terrain/{padding-1-degree.js → padding-1-degree.ts} +713 -539
  122. package/semiplugins/shape-on-terrain/terrain-polygon/adapters.ts +69 -0
  123. package/semiplugins/shape-on-terrain/terrain-polygon/data/cache-shortcuts.md +20 -0
  124. package/semiplugins/shape-on-terrain/terrain-polygon/data/cache.ts +149 -0
  125. package/semiplugins/shape-on-terrain/terrain-polygon/data/index-polygon-map.ts +58 -0
  126. package/semiplugins/shape-on-terrain/terrain-polygon/data/manager.ts +4 -0
  127. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.js +196 -0
  128. package/semiplugins/shape-on-terrain/terrain-polygon/data/master-worker.ts +209 -0
  129. package/semiplugins/shape-on-terrain/terrain-polygon/data/polygon-to-triangles.ts +144 -0
  130. package/semiplugins/shape-on-terrain/terrain-polygon/data/random.ts +165 -0
  131. package/semiplugins/shape-on-terrain/terrain-polygon/data/readme.md +5 -0
  132. package/semiplugins/shape-on-terrain/terrain-polygon/data/types.ts +37 -0
  133. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker-contact.ts +81 -0
  134. package/semiplugins/shape-on-terrain/terrain-polygon/data/worker.js +146 -0
  135. package/semiplugins/shape-on-terrain/terrain-polygon/notes.md +90 -0
  136. package/semiplugins/shape-on-terrain/terrain-polygon/terrain-polygon.ts +265 -0
  137. package/semiplugins/shape-on-terrain/terrain-polygon/types.ts +69 -0
  138. package/semiplugins/shell/bbox-renderer/index.ts +2 -0
  139. package/semiplugins/shell/bbox-renderer/{logic.js → logic.ts} +273 -249
  140. package/semiplugins/shell/bbox-renderer/object.ts +129 -0
  141. package/semiplugins/type.ts +8 -0
  142. package/semiplugins/utility/{container-plugin.js → container-plugin.ts} +126 -94
  143. package/semiplugins/utility/{object-pass-container-plugin.js → object-pass-container-plugin.ts} +101 -80
  144. package/shaders/fragment-toy/firework.js +1 -1
  145. package/shaders/fragment-toy/singularity.js +5 -2
  146. package/terrain-plugin.mmd +83 -0
  147. package/tests/Math/arc-sampling-test.js +367 -0
  148. package/tests/Math/arc-sampling-test.ts +429 -0
  149. package/tests/Math/arc.test.ts +77 -0
  150. package/tests/Math/junction/arc-limit.test.ts +7 -0
  151. package/tests/Math/junction/arc-plane-points.test.ts +196 -0
  152. package/tests/Math/junction/arc-plane.test.ts +172 -0
  153. package/tests/Math/junction/line-sphere.test.ts +127 -0
  154. package/tests/Math/junction/plane-plane.test.ts +91 -0
  155. package/tests/Math/plane-test.ts +17 -0
  156. package/tests/Math/plane.test.ts +43 -0
  157. package/tests/Math/vec3.test.ts +33 -0
  158. package/tracks/point-heat-map/adaptors/timetracksplugin-format-to-this.js +78 -63
  159. package/tracks/point-heat-map/index.js +0 -1
  160. package/tracks/point-heat-map/plugin-webworker.js +148 -121
  161. package/tracks/point-heat-map/point-to-heat-map-flow.js +150 -121
  162. package/tracks/point-heat-map/readme.md +15 -0
  163. package/tracks/point-tracks/key-methods.js +3 -2
  164. package/tracks/point-tracks/plugin.js +487 -394
  165. package/tracks/timetracks/adaptors-line-strip.js +79 -65
  166. package/tracks/timetracks/plugin-line-strip.js +295 -240
  167. package/tracks/timetracks/program-line-strip.js +495 -411
  168. package/tracks/timetracks/programpoint-line-strip.js +137 -109
  169. package/tracks/timetracks/readme.md +1 -0
  170. package/tsconfig.json +22 -0
  171. package/types/@pirireis/webglobe.d.ts +102 -0
  172. package/types/delaunator.d.ts +40 -0
  173. package/types/earcut.d.ts +11 -0
  174. package/types/rbush.d.ts +57 -0
  175. package/types.ts +319 -0
  176. package/util/account/bufferoffsetmanager.js +209 -176
  177. package/util/account/create-buffermap-orchastration.ts +85 -0
  178. package/util/account/index.js +6 -3
  179. package/util/account/single-attribute-buffer-management/{buffer-manager.js → buffer-manager.ts} +151 -117
  180. package/util/account/single-attribute-buffer-management/{buffer-orchestrator.js → buffer-orchestrator.ts} +238 -212
  181. package/util/account/single-attribute-buffer-management/{buffer-orchestrator1.js → buffer-orchestrator1.ts} +184 -159
  182. package/util/account/single-attribute-buffer-management/{index.js → index.ts} +11 -4
  183. package/util/account/single-attribute-buffer-management/{object-store.js → object-store.ts} +76 -55
  184. package/util/account/single-attribute-buffer-management/types.ts +43 -0
  185. package/util/account/util.js +22 -18
  186. package/util/algorithms/index.js +0 -1
  187. package/util/algorithms/search-binary.js +26 -25
  188. package/util/build-strategy/{static-dynamic.js → static-dynamic.ts} +50 -41
  189. package/util/check/index.js +0 -1
  190. package/util/check/typecheck.ts +74 -0
  191. package/util/{frame-counter-trigger.js → frame-counter-trigger.ts} +99 -84
  192. package/util/geometry/{index.js → index.ts} +155 -121
  193. package/util/gl-util/buffer/{attribute-loader.js → attribute-loader.ts} +84 -62
  194. package/util/gl-util/buffer/{index.js → index.ts} +6 -3
  195. package/util/gl-util/draw-options/{methods.js → methods.ts} +47 -32
  196. package/util/gl-util/uniform-block/{manager.js → manager.ts} +232 -190
  197. package/util/{webglobe/gldefaultstates.js → globe-default-gl-states.ts} +5 -4
  198. package/util/helper-methods.ts +9 -0
  199. package/util/index.js +9 -10
  200. package/util/interpolation/index.js +0 -1
  201. package/util/interpolation/timetrack/index.js +9 -2
  202. package/util/interpolation/timetrack/timetrack-interpolator.js +94 -79
  203. package/util/interpolation/timetrack/web-worker.js +51 -46
  204. package/util/picking/{fence.js → fence.ts} +47 -41
  205. package/util/picking/picker-displayer.ts +226 -0
  206. package/util/programs/draw-from-pixel-coords.js +201 -164
  207. package/util/programs/{draw-texture-on-canvas.js → draw-texture-on-canvas.ts} +92 -67
  208. package/util/programs/supersampletotextures.js +130 -97
  209. package/util/programs/texturetoglobe.js +153 -128
  210. package/util/shaderfunctions/{geometrytransformations.js → geometrytransformations.ts} +169 -41
  211. package/util/shaderfunctions/index.js +2 -2
  212. package/util/shaderfunctions/nodata.js +4 -2
  213. package/util/shaderfunctions/noisefunctions.js +10 -7
  214. package/util/{webglobjectbuilders.js → webglobjectbuilders.ts} +446 -358
  215. package/vectorfield/arrowfield/adaptor.js +11 -11
  216. package/vectorfield/arrowfield/index.js +3 -3
  217. package/vectorfield/arrowfield/plugin.js +128 -83
  218. package/vectorfield/waveparticles/adaptor.js +16 -15
  219. package/vectorfield/waveparticles/index.js +3 -3
  220. package/vectorfield/waveparticles/plugin.ts +506 -0
  221. package/vectorfield/wind/adapters/image-to-fields.ts +74 -0
  222. package/vectorfield/wind/adapters/types.ts +12 -0
  223. package/vectorfield/wind/{imagetovectorfieldandmagnitude.js → imagetovectorfieldandmagnitude.ts} +78 -56
  224. package/vectorfield/wind/index.js +5 -5
  225. package/vectorfield/wind/plugin-persistant copy.ts +461 -0
  226. package/vectorfield/wind/plugin-persistant.ts +483 -0
  227. package/vectorfield/wind/plugin.js +883 -685
  228. package/vectorfield/wind/vectorfieldimage.js +27 -23
  229. package/write-text/{context-text-bulk.js → context-text-bulk.ts} +285 -200
  230. package/write-text/context-text3.ts +252 -0
  231. package/write-text/{context-text4.js → context-text4.ts} +231 -146
  232. package/write-text/context-textDELETE.js +125 -94
  233. package/write-text/objectarraylabels/{index.js → index.ts} +2 -2
  234. package/write-text/objectarraylabels/objectarraylabels.d.ts +72 -0
  235. package/write-text/objectarraylabels/objectarraylabels.js +247 -200
  236. package/Math/matrix4.js +0 -1
  237. package/Math/tessellation/earcut/adapters.js +0 -37
  238. package/Math/tessellation/hybrid-triangle-tessellation-meta.js +0 -123
  239. package/Math/tessellation/methods.js +0 -46
  240. package/Math/tessellation/shred-input.js +0 -18
  241. package/Math/tessellation/tile-merger.js +0 -298
  242. package/Math/tessellation/tiler.js +0 -50
  243. package/Math/tessellation/triangle-tessellation-meta.js +0 -523
  244. package/Math/tessellation/triangle-tessellation.js +0 -14
  245. package/Math/tessellation/types.js +0 -1
  246. package/Math/tessellation/zoom-catch.js +0 -1
  247. package/Math/types.js +0 -1
  248. package/investigation-tools/draw/tiles/adapters.js +0 -67
  249. package/programs/line-on-globe/linestrip/data.js +0 -4
  250. package/programs/polygon-on-globe/texture-dem-triangle-test-plugin-triangle.js +0 -328
  251. package/programs/polygon-on-globe/texture-dem-triangles.js +0 -268
  252. package/programs/vectorfields/logics/drawrectangleparticles.js +0 -114
  253. package/programs/vectorfields/logics/drawrectangleparticles1.js +0 -112
  254. package/programs/vectorfields/logics/ubo-new.js +0 -25
  255. package/range-tools-on-terrain/bearing-line/types.js +0 -1
  256. package/range-tools-on-terrain/circle-line-chain/types.js +0 -1
  257. package/range-tools-on-terrain/range-ring/rangeringangletext.js +0 -331
  258. package/range-tools-on-terrain/range-ring/types.js +0 -9
  259. package/semiplugins/interface.js +0 -1
  260. package/semiplugins/shape-on-terrain/terrain-cover/texture-dem-cover.js +0 -1
  261. package/semiplugins/shell/bbox-renderer/index.js +0 -2
  262. package/semiplugins/shell/bbox-renderer/object.js +0 -65
  263. package/semiplugins/type.js +0 -1
  264. package/types.js +0 -19
  265. package/util/account/create-buffermap-orchastration.js +0 -39
  266. package/util/account/single-attribute-buffer-management/types.js +0 -1
  267. package/util/check/typecheck.js +0 -66
  268. package/util/gl-util/uniform-block/types.js +0 -1
  269. package/util/picking/picker-displayer.js +0 -134
  270. package/util/webglobe/index.js +0 -2
  271. package/vectorfield/waveparticles/plugin.js +0 -290
  272. package/write-text/context-text3.js +0 -167
@@ -0,0 +1,483 @@
1
+ /**
2
+ * Author: Toprak Nihat Deniz Ozturk
3
+ */
4
+
5
+ import { Globe } from "../../types";
6
+ import { imageToFields } from "./adapters/image-to-fields";
7
+ import ParticlePlugin from "../waveparticles/plugin";
8
+ import { createImageFromBase64 } from "../../util/webglobjectbuilders";
9
+ import { TexturePointSampler } from "../../heatwave/texture-point-sampler";
10
+ import imageToMagnitude, { imageToRadianAngle } from "./imagetovectorfieldandmagnitude";
11
+ import { WindData, LegendData } from "./adapters/types.js";
12
+ import { isBoolean } from "../../util/check/typecheck";
13
+
14
+ /**
15
+ * Shader Documentation:
16
+ * * Vector field escape value
17
+ * texture2D(u_wind, pos).rg == vec2(0.0, 0.0) is used as escape value.
18
+ * In sea wind maps, land areas have rg values of 0.0.
19
+ * The probability of a real particle having rg == vec2(0.0, 0.0) is low.
20
+ * Must have lowest value in both horizontal and vertical dimensions.
21
+ */
22
+
23
+ type WindDataMeta = {
24
+ width: number;
25
+ height: number;
26
+ bbox: number[]; // [minLon, minLat, maxLon, maxLat]
27
+ flipY?: boolean;
28
+ };
29
+
30
+ type WindPluginOptions = {
31
+ fadeOpacity?: number;
32
+ speedFactor?: number;
33
+ dropRate?: number;
34
+ dropRateBump?: number;
35
+ baseOpacity?: number;
36
+ wingSize?: number;
37
+ tailSize?: number;
38
+ minSpeed?: number;
39
+ maxSpeed?: number;
40
+ height?: number;
41
+ numParticles?: number;
42
+ legendData?: LegendData;
43
+ };
44
+
45
+ const windyLegendData: LegendData = {
46
+ thresholds: [0, 3, 3, 5, 5, 7, 10, 10, 13, 15, 15, 17, 20, 20, 25, 25, 30],
47
+ values: [
48
+ "#6271B8",
49
+ "#6271B8",
50
+ "#6271B8",
51
+ "#6271B8",
52
+ "#3D6EA3",
53
+ "#4A94AA",
54
+ "#4A9294",
55
+ "#4D8E7C",
56
+ "#4CA44C",
57
+ "#67A436",
58
+ "#A28740",
59
+ "#A26D5C",
60
+ "#8D3F5C",
61
+ "#974B91",
62
+ "#5F64A0",
63
+ "#5B88A1",
64
+ "#5B88A1"
65
+ ]
66
+ };
67
+
68
+ export default class WindPlugin {
69
+ public id: string;
70
+ public globe!: Globe;
71
+ private gl: WebGL2RenderingContext | null = null;
72
+ private particlePlugin!: ParticlePlugin;
73
+ private windMetadata: WindDataMeta;
74
+ private _legendData: LegendData;
75
+ private options: WindPluginOptions;
76
+ private windData: WindData | null;
77
+ private _height: number;
78
+ private _speedFactor: number;
79
+ private _dropRate: number;
80
+ private texturePointSampler?: TexturePointSampler;
81
+ private texturePointSamplerAngle?: TexturePointSampler;
82
+
83
+ /**
84
+ * @param id - Plugin identifier
85
+ * @param windDataMeta - Wind data metadata
86
+ * @param windDataMeta.width - image width
87
+ * @param windDataMeta.height - image height
88
+ * @param windDataMeta.bbox - bounding box [minLon, minLat, maxLon, maxLat]
89
+ * @param options - Plugin options
90
+ * @param options.fadeOpacity - how fast the particle trails fade on each frame | between 0 - 1 | default 0.746
91
+ * @param options.speedFactor - how fast the particles move | between 0 - 1 | default 0.6
92
+ * @param options.dropRate - how often the particles move to a random place | between 0 - 1 | default 0.007
93
+ * @param options.dropRateBump - drop rate increase relative to individual particle speed
94
+ * @param options.baseOpacity - opacity of drawn particle trails | between 0 - 1 | default 1.0
95
+ * @param options.wingSize - wing size of particle arrow | positive number | default 7.0
96
+ * @param options.tailSize - tail size of particle arrow | positive number | default 1.0
97
+ * @param options.minSpeed - minimum speed threshold | positive number | default 0.0
98
+ * @param options.maxSpeed - maximum speed threshold | positive number | default 1000.0
99
+ * @param options.height - height of the particles | number | default 0.0
100
+ * @param options.numParticles - number of particles | positive integer | default 40000
101
+ * @param options.legendData - legend data for color mapping
102
+ */
103
+ constructor(
104
+ id: string,
105
+ windDataMeta: WindDataMeta,
106
+ options: WindPluginOptions = {}
107
+ ) {
108
+ this.id = id;
109
+ this.windMetadata = windDataMeta;
110
+ this._legendData = options.legendData || windyLegendData;
111
+
112
+ this.options = {
113
+ fadeOpacity: options.fadeOpacity ?? 0.746,
114
+ speedFactor: options.speedFactor ?? 0.6,
115
+ dropRate: options.dropRate ?? 0.007,
116
+ dropRateBump: options.dropRateBump ?? 0.001,
117
+ baseOpacity: options.baseOpacity ?? 1.0,
118
+ wingSize: options.wingSize ?? 7.0,
119
+ tailSize: options.tailSize ?? 1.0,
120
+ minSpeed: options.minSpeed ?? 0.0,
121
+ maxSpeed: options.maxSpeed ?? 1000.0,
122
+ height: options.height ?? 0.0,
123
+ numParticles: options.numParticles ?? 40000,
124
+ legendData: this._legendData
125
+ };
126
+
127
+ this.windData = null;
128
+ this._height = this.options.height!;
129
+ this._speedFactor = this.options.speedFactor!;
130
+ this._dropRate = this.options.dropRate!;
131
+ }
132
+
133
+ // Globe plugin init method
134
+ init(globe: Globe, gl: WebGL2RenderingContext): void {
135
+ this.globe = globe;
136
+ this.gl = gl;
137
+
138
+ // Initialize the particle plugin with appropriate options
139
+ const { bbox, width, height, flipY } = this.windMetadata;
140
+
141
+ this.particlePlugin = new ParticlePlugin(
142
+ `${this.id}_particles`,
143
+ {
144
+ dataWidth: width,
145
+ dataHeight: height,
146
+ fadeOpacity: this.options.fadeOpacity,
147
+ opacity: this.options.baseOpacity,
148
+ speed: this._speedFactor,
149
+ dropRate: this._dropRate,
150
+ height: this._height,
151
+ minLon: bbox[0],
152
+ minLat: bbox[1] < -85 ? -85 : bbox[1],
153
+ maxLon: bbox[2],
154
+ maxLat: bbox[3] > 85 ? 85 : bbox[3],
155
+ particleCount: this.options.numParticles,
156
+ flipY: flipY ?? true,
157
+ useColorTexture: false, // TODO: under test.. make it true later
158
+ useSpeedTexture: true,
159
+ minSpeedThreshold: this.options.minSpeed,
160
+ maxSpeedThreshold: this.options.maxSpeed,
161
+ tailSize: this.options.tailSize!,
162
+ wingSize: this.options.wingSize!
163
+ }
164
+ );
165
+
166
+ this.particlePlugin.init(globe, gl);
167
+ // apply initial speed thresholds from options
168
+ this.particlePlugin.setSpeedThresholds(this.options.minSpeed!, this.options.maxSpeed!);
169
+ }
170
+
171
+ draw3D(): void {
172
+ if (this.particlePlugin) {
173
+ this.particlePlugin.draw3D();
174
+ }
175
+ }
176
+
177
+ free(): void {
178
+ if (this.particlePlugin) {
179
+ this.particlePlugin.free();
180
+ }
181
+ if (this.texturePointSampler) {
182
+ this.texturePointSampler = undefined;
183
+ }
184
+ if (this.texturePointSamplerAngle) {
185
+ this.texturePointSamplerAngle = undefined;
186
+ }
187
+ }
188
+
189
+ // ===== Wind Data Management =====
190
+
191
+ /**
192
+ * Set wind data from base64 encoded image
193
+ * @param windData - Wind data object
194
+ * @param windData.image - base64 encoded image
195
+ * @param windData.width - image width
196
+ * @param windData.height - image height
197
+ * @param windData.uMin - minimum u value
198
+ * @param windData.vMin - minimum v value
199
+ * @param windData.uMax - maximum u value
200
+ * @param windData.vMax - maximum v value
201
+ * @param windData.bbox - bounding box [minLon, minLat, maxLon, maxLat]
202
+ */
203
+ setWindDataWithImageBase64(windData: {
204
+ image: string;
205
+ width: number;
206
+ height: number;
207
+ uMin: number;
208
+ vMin: number;
209
+ uMax: number;
210
+ vMax: number;
211
+ bbox?: number[];
212
+ }): void {
213
+ const image = createImageFromBase64(windData.image);
214
+ image.onload = () => {
215
+ const fullWindData: WindData = {
216
+ image: image,
217
+ uMin: windData.uMin,
218
+ vMin: windData.vMin,
219
+ uMax: windData.uMax,
220
+ vMax: windData.vMax
221
+ };
222
+ this.setWind(fullWindData);
223
+ };
224
+ }
225
+
226
+ /**
227
+ * Set wind data from HTMLImageElement
228
+ */
229
+ setWind(windData: WindData): void {
230
+ this.windData = windData;
231
+
232
+ if (!this.particlePlugin) {
233
+ return;
234
+ }
235
+
236
+ // Convert wind image to vector field, speed field, and color field
237
+ const { vectorFieldData, speedFieldData, colorFieldData } = imageToFields(
238
+ windData,
239
+ this._legendData
240
+ );
241
+
242
+ // Update the particle plugin with the new data
243
+ this.particlePlugin.setVectorFieldData(vectorFieldData, {
244
+ dataWidth: windData.image.width,
245
+ dataHeight: windData.image.height,
246
+ flipY: this.windMetadata.flipY
247
+ });
248
+
249
+ this.particlePlugin.setSpeedField(speedFieldData);
250
+ this.particlePlugin.setColorField(colorFieldData);
251
+
252
+ // Update texture point samplers if they exist
253
+ this._setCoorcinatesDataCalculatorData();
254
+ }
255
+
256
+ // ===== Legend and Color Management =====
257
+
258
+ /**
259
+ * Set legend data for color mapping
260
+ * @param legendData - Legend data object
261
+ * @param legendData.thresholds - list of speed thresholds
262
+ * @param legendData.values - list of colors in hex format like #ff0000
263
+ */
264
+ setLegend(legendData: LegendData): void {
265
+ this._legendData = legendData;
266
+
267
+ // If wind data is already set, re-process to update colors
268
+ if (this.windData && this.particlePlugin) {
269
+ const { vectorFieldData, speedFieldData, colorFieldData } = imageToFields(
270
+ this.windData,
271
+ this._legendData
272
+ );
273
+ this.particlePlugin.setColorField(colorFieldData);
274
+ }
275
+ }
276
+
277
+
278
+ setFlipY(flipY: boolean): void {
279
+ isBoolean(flipY);
280
+ this.windMetadata.flipY = flipY;
281
+ if (this.particlePlugin && this.windData) {
282
+ this.setWind(this.windData);
283
+ }
284
+ }
285
+
286
+
287
+ setDrawTextureMaxPixelOnDimension(value: number): void {
288
+ if (this.particlePlugin) {
289
+ this.particlePlugin.setDrawTextureMaxPixelOnDimension(value);
290
+ }
291
+ }
292
+ // ===== Property Setters =====
293
+
294
+ set height(value: number) {
295
+ this._height = value;
296
+ if (this.particlePlugin) {
297
+ this.particlePlugin.setHeight(value);
298
+ }
299
+ }
300
+
301
+ get height(): number {
302
+ return this._height;
303
+ }
304
+
305
+ set minSpeed(value: number) {
306
+ this.options.minSpeed = value;
307
+ if (this.particlePlugin) {
308
+ this.particlePlugin.setMinSpeedThreshold(value);
309
+ }
310
+ }
311
+
312
+ get minSpeed(): number {
313
+ return this.options.minSpeed!;
314
+ }
315
+
316
+ set maxSpeed(value: number) {
317
+ this.options.maxSpeed = value;
318
+ if (this.particlePlugin) {
319
+ this.particlePlugin.setMaxSpeedThreshold(value);
320
+ }
321
+ }
322
+
323
+ get maxSpeed(): number {
324
+ return this.options.maxSpeed!;
325
+ }
326
+
327
+ set fadeOpacity(value: number) {
328
+ this.options.fadeOpacity = value;
329
+ if (this.particlePlugin) {
330
+ this.particlePlugin.setFadeOpacity(value);
331
+ }
332
+ }
333
+
334
+ get fadeOpacity(): number {
335
+ return this.options.fadeOpacity!;
336
+ }
337
+
338
+ set speedFactor(value: number) {
339
+ this._speedFactor = value;
340
+ if (this.particlePlugin) {
341
+ this.particlePlugin.setParticleSpeed(value);
342
+ }
343
+ }
344
+
345
+ get speedFactor(): number {
346
+ return this._speedFactor;
347
+ }
348
+
349
+ set dropRate(value: number) {
350
+ this._dropRate = value;
351
+ if (this.particlePlugin) {
352
+ this.particlePlugin.setDropRate(value);
353
+ }
354
+ }
355
+
356
+ get dropRate(): number {
357
+ return this._dropRate;
358
+ }
359
+
360
+ set dropRateBump(value: number) {
361
+ this.options.dropRateBump = value;
362
+ // Note: ParticlePlugin doesn't have dropRateBump parameter
363
+ // This would need to be added to ParticlePlugin if needed
364
+ }
365
+
366
+ get dropRateBump(): number {
367
+ return this.options.dropRateBump!;
368
+ }
369
+
370
+ set baseOpacity(value: number) {
371
+ this.options.baseOpacity = value;
372
+ if (this.particlePlugin) {
373
+ this.particlePlugin.setOpacity(value);
374
+ }
375
+ }
376
+
377
+ get baseOpacity(): number {
378
+ return this.options.baseOpacity!;
379
+ }
380
+
381
+ set numParticles(value: number) {
382
+ this.options.numParticles = value;
383
+ if (this.particlePlugin) {
384
+ this.particlePlugin.setParticleCount(value);
385
+ }
386
+ }
387
+
388
+ get numParticles(): number {
389
+ return this.options.numParticles!;
390
+ }
391
+
392
+ /**
393
+ * Set wing and tail size for particle arrows
394
+ */
395
+ setParticleDimensions(tail: number, wing: number): void {
396
+ this.options.tailSize = tail;
397
+ this.options.wingSize = wing;
398
+ if (this.particlePlugin) {
399
+ this.particlePlugin.setParticleDimensions(tail, wing);
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Set particle color (used when not using color field)
405
+ */
406
+ setParticleColor(color: number[]): void {
407
+ if (this.particlePlugin) {
408
+ this.particlePlugin.setParticleColor(color);
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Set bounding box
414
+ */
415
+ setBBox(bbox: { minLon: number; minLat: number; maxLon: number; maxLat: number }): void {
416
+ // rescale
417
+
418
+ if (this.particlePlugin) {
419
+ this.particlePlugin.setBBox({
420
+ minLon: bbox.minLon,
421
+ minLat: bbox.minLat < -85 ? -85 : bbox.minLat,
422
+ maxLon: bbox.maxLon,
423
+ maxLat: bbox.maxLat > 85 ? 85 : bbox.maxLat
424
+ });
425
+ }
426
+ // Update metadata
427
+ this.windMetadata.bbox = [bbox.minLon, bbox.minLat, bbox.maxLon, bbox.maxLat];
428
+ }
429
+
430
+ // ===== Texture Point Sampler (for backward compatibility) =====
431
+
432
+ /**
433
+ * Get texture point sampler for magnitude or angle
434
+ * @param type - 'magnitude' or 'angle'
435
+ */
436
+ getTexturePointSampler(type: 'magnitude' | 'angle' = 'magnitude'): TexturePointSampler {
437
+ if (type === 'magnitude') {
438
+ if (!this.texturePointSampler) {
439
+ this._createTexturePointSampler();
440
+ this._setCoorcinatesDataCalculatorData();
441
+ }
442
+ return this.texturePointSampler!;
443
+ } else if (type === 'angle') {
444
+ if (!this.texturePointSamplerAngle) {
445
+ this._createTexturePointSamplerAngle();
446
+ this._setCoorcinatesDataCalculatorData();
447
+ }
448
+ return this.texturePointSamplerAngle!;
449
+ } else {
450
+ throw new Error(`WindPlugin.getTexturePointSampler: type must be either 'magnitude' or 'angle'.`);
451
+ }
452
+ }
453
+
454
+ private _createTexturePointSamplerAngle(): void {
455
+ const { bbox, width, height } = this.windMetadata;
456
+ this.texturePointSamplerAngle = new TexturePointSampler(bbox as [number, number, number, number], width, height);
457
+ }
458
+
459
+ private _createTexturePointSampler(): void {
460
+ const { bbox, width, height } = this.windMetadata;
461
+ this.texturePointSampler = new TexturePointSampler(bbox as [number, number, number, number], width, height);
462
+ }
463
+
464
+ private _setCoorcinatesDataCalculatorData(): void {
465
+ if (!this.windData) {
466
+ return;
467
+ }
468
+ const windDataWithDimensions = {
469
+ ...this.windData,
470
+ width: this.windData.image.width,
471
+ height: this.windData.image.height
472
+ };
473
+ if (this.texturePointSamplerAngle) {
474
+ const angle = imageToRadianAngle(windDataWithDimensions as any);
475
+ this.texturePointSamplerAngle.updateTextureData(0, angle, angle);
476
+ }
477
+ if (this.texturePointSampler) {
478
+ const magnitude = imageToMagnitude(windDataWithDimensions as any);
479
+ this.texturePointSampler.updateTextureData(0, magnitude, magnitude);
480
+ }
481
+ }
482
+ }
483
+