@pirireis/webglobeplugins 1.0.2 → 1.0.3

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