@pirireis/webglobeplugins 0.15.21-alpha → 0.15.24

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 (33) hide show
  1. package/Math/arc.js +1 -2
  2. package/Math/circle-cdf-points.js +1 -170
  3. package/Math/circle.js +0 -25
  4. package/Math/vec3.js +1 -1
  5. package/altitude-locator/plugin.js +1 -1
  6. package/package.json +1 -1
  7. package/point-tracks/plugin.js +5 -6
  8. package/programs/line-on-globe/lines-color-instanced-flat.js +0 -1
  9. package/programs/point-on-globe/element-globe-surface-glow.js +0 -1
  10. package/programs/totems/camerauniformblock.js +7 -0
  11. package/programs/totems/canvas-webglobe-info.js +9 -9
  12. package/programs/totems/globe-changes.js +21 -14
  13. package/range-tools-on-terrain/bearing-line/plugin.js +2 -5
  14. package/range-tools-on-terrain/circle-line-chain/chain-list-map.js +4 -9
  15. package/range-tools-on-terrain/circle-line-chain/plugin.js +4 -2
  16. package/range-tools-on-terrain/range-ring/adapters.js +25 -9
  17. package/range-tools-on-terrain/range-ring/plugin.js +200 -5
  18. package/range-tools-on-terrain/range-ring/types.js +9 -1
  19. package/semiplugins/lightweight/line-plugin.js +33 -15
  20. package/semiplugins/shape-on-terrain/arc-plugin.js +162 -99
  21. package/semiplugins/shape-on-terrain/circle-plugin.js +170 -83
  22. package/semiplugins/shape-on-terrain/padding-1-degree.js +244 -63
  23. package/util/account/single-attribute-buffer-management/buffer-orchestrator.js +1 -1
  24. package/util/build-strategy/static-dynamic.js +11 -1
  25. package/util/frame-counter-trigger.js +84 -0
  26. package/wind/imagetovectorfieldandmagnitude.js +23 -0
  27. package/wind/index.js +2 -2
  28. package/wind/plugin.js +30 -9
  29. package/write-text/context-text4.js +140 -0
  30. package/Math/arc-generate-points copy.js +0 -366
  31. package/Math/globe-util/horizon-plane.js +0 -112
  32. package/altitude-locator/draw-subset-obj.js +0 -16
  33. package/semiplugins/shape-on-terrain/derived/padding-plugin.js +0 -101
@@ -16,23 +16,23 @@ import { BufferManager } from '../../util/account/single-attribute-buffer-manage
16
16
  import { BufferOrchestrator } from '../../util/account/single-attribute-buffer-management/buffer-orchestrator';
17
17
  import { LineStripProgramCache } from '../../programs/line-on-globe/linestrip/linestrip';
18
18
  import { opacityCheck, colorCheck } from '../../util/check/typecheck';
19
+ import { FrameCounterTrigger } from '../../util/frame-counter-trigger';
19
20
  const initialCapacity = 2; // initial capacity for the buffer managers
20
21
  // const _float32Array = new Float32Array(360 * 3 * 2).fill(NaN);
21
22
  export class Padding1DegreePlugin {
22
23
  id;
23
24
  globe = null;
24
25
  bufferOrchestrator;
25
- bufferManagersMap;
26
+ bufferManagerMap;
26
27
  lineProgram = null;
27
- _opacityLODCoef = 1;
28
- _pluginOpacity = 1; // this is used to set the opacity of the plugin
29
- _innerPaddingRatio = 0.9; //
28
+ _innerPaddingRatio = 0.95; //
30
29
  _float32Array = null; // this is used to forward the data to the buffer manager
31
30
  _uboHandler = null; // this is used to forward the data to the shader program
32
31
  _bufferNames = ["position2d", "position3d"];
33
32
  _vao = null; // this is used to store the VAO for the plugin
34
33
  _freed = false; // this is used to check if the plugin is freed or not
35
- _lastCAM_LOD = { camInfo: -1, lod: -1 }; // this is used to store the last zoom and lod values
34
+ _userOpacity = 1;
35
+ _adaptiveOpacityMultiplier = 1;
36
36
  _dataMap = new Map();
37
37
  _options = {
38
38
  bufferType: "STATIC_DRAW",
@@ -43,9 +43,10 @@ export class Padding1DegreePlugin {
43
43
  adaptiveOpacity: true, // if true, the opacity will be adaptive to the LOD
44
44
  isMSL: false // if true, no elevation of terrain
45
45
  };
46
+ _frameCounterTrigger = null;
46
47
  constructor(id, options = null) {
47
48
  this.id = id;
48
- this.bufferManagersMap = new Map();
49
+ this.bufferManagerMap = new Map();
49
50
  this.lineProgram = null;
50
51
  this._options = options ? { ...this._options, ...options } : this._options;
51
52
  this.bufferOrchestrator = new BufferOrchestrator();
@@ -53,6 +54,21 @@ export class Padding1DegreePlugin {
53
54
  this._bufferNames.push("color");
54
55
  }
55
56
  }
57
+ increaseSpace(amount) {
58
+ if (this._freed) {
59
+ console.warn("Plugin is freed, cannot increase space");
60
+ return;
61
+ }
62
+ if (this.globe === null) {
63
+ console.warn("Globe is not initialized.");
64
+ return;
65
+ }
66
+ if (typeof amount !== "number" || amount <= 0) {
67
+ console.warn("Invalid amount, must be a positive number");
68
+ return;
69
+ }
70
+ this.bufferOrchestrator.ensureSpace(amount, this.bufferManagerMap);
71
+ }
56
72
  insertBulk(inputs) {
57
73
  if (this.globe === null) {
58
74
  console.warn("Globe is not initialized, cannot insert input");
@@ -64,16 +80,78 @@ export class Padding1DegreePlugin {
64
80
  }
65
81
  const wrapper = [null];
66
82
  this._float32Array = new Float32Array(360 * 4 * 4); // largest float32Array
83
+ let newItemCount = 0;
84
+ for (let i = 0; i < inputs.length; i++) {
85
+ if (!this._dataMap.has(inputs[i].key)) {
86
+ newItemCount++;
87
+ }
88
+ }
89
+ this.bufferOrchestrator.ensureSpace(newItemCount, this.bufferManagerMap);
67
90
  for (let i = 0; i < inputs.length; i++) {
68
91
  const coords = preAdapter(this.globe, inputs[i], this._innerPaddingRatio, null);
69
92
  const paddingInput = { ...inputs[i], ...coords };
70
93
  this._dataMap.set(paddingInput.key, paddingInput);
71
94
  wrapper[0] = paddingInput;
72
- this.bufferOrchestrator.insertBulk(wrapper, this.bufferManagersMap, this._bufferNames);
95
+ this.bufferOrchestrator.insertBulk(wrapper, this.bufferManagerMap, this._bufferNames);
73
96
  }
74
97
  this._float32Array = null;
75
98
  this.globe?.DrawRender();
76
99
  }
100
+ updateColorRatios(key, colorRatios, drawRender = true) {
101
+ if (this._freed) {
102
+ console.warn("Plugin is freed, cannot update color");
103
+ return;
104
+ }
105
+ if (this.globe === null) {
106
+ console.warn("Globe is not initialized, cannot update color");
107
+ return;
108
+ }
109
+ if (!this._options.variativeColorsOn) {
110
+ console.warn("VariativeColors are not enabled");
111
+ return;
112
+ }
113
+ if (!this._dataMap.has(key)) {
114
+ console.warn(`Key ${key} does not exist in the data map`);
115
+ return;
116
+ }
117
+ const paddingInput = this._dataMap.get(key);
118
+ if (!paddingInput) {
119
+ console.warn(`Padding input for key ${key} is not found`);
120
+ return;
121
+ }
122
+ this._float32Array = new Float32Array(360 * 4 * 4); // largest float32Array
123
+ paddingInput.colorsRatios = colorRatios;
124
+ this.bufferOrchestrator.updateBulk([paddingInput], this.bufferManagerMap, ["color"]);
125
+ this._float32Array = null;
126
+ if (drawRender) {
127
+ this.globe.DrawRender();
128
+ }
129
+ }
130
+ updateCoordinates(items) {
131
+ if (this._freed) {
132
+ console.warn("Plugin is freed, cannot update coordinates");
133
+ return;
134
+ }
135
+ if (this.globe === null) {
136
+ console.warn("Globe is not initialized, cannot update coordinates");
137
+ return;
138
+ }
139
+ this._float32Array = new Float32Array(360 * 4 * 4); // largest float32Array
140
+ const updateKeys = [];
141
+ for (const item of items) {
142
+ const paddingInput = this._dataMap.get(item.key);
143
+ if (!paddingInput) {
144
+ console.warn(`Padding input for key ${item.key} is not found`);
145
+ continue;
146
+ }
147
+ paddingInput.center = item.center;
148
+ paddingInput.radius = item.radius;
149
+ updateKeys.push(item.key);
150
+ }
151
+ this._buildPaddings("input", updateKeys);
152
+ this._float32Array = null;
153
+ this.globe.DrawRender();
154
+ }
77
155
  deleteBulk(keys) {
78
156
  if (this.globe === null) {
79
157
  console.warn("Globe is not initialized, cannot delete data");
@@ -83,10 +161,10 @@ export class Padding1DegreePlugin {
83
161
  console.warn("Plugin is freed, cannot delete data");
84
162
  return;
85
163
  }
86
- this.bufferOrchestrator.deleteBulk(keys, this.bufferManagersMap);
164
+ this.bufferOrchestrator.deleteBulk(keys, this.bufferManagerMap);
87
165
  this.globe?.DrawRender();
88
166
  }
89
- setPluginOpacity(opacity) {
167
+ setPluginOpacity(opacity, drawRender = false) {
90
168
  if (this._freed) {
91
169
  console.warn("Plugin is freed, cannot set opacity");
92
170
  return;
@@ -96,9 +174,10 @@ export class Padding1DegreePlugin {
96
174
  return;
97
175
  }
98
176
  opacityCheck(opacity);
99
- this._opacityLODCoef = opacity;
100
- this._uboHandler?.updateSingle("u_opacity", new Float32Array([opacity]));
101
- this.globe.DrawRender();
177
+ this._userOpacity = opacity;
178
+ if (drawRender) {
179
+ this.globe.DrawRender();
180
+ }
102
181
  }
103
182
  setDefaultColor(color) {
104
183
  if (this._freed) {
@@ -128,10 +207,18 @@ export class Padding1DegreePlugin {
128
207
  this._buildPaddings("elevation");
129
208
  this.globe?.DrawRender();
130
209
  }
131
- init(globe) {
210
+ init(globe, gl) {
132
211
  this.globe = globe;
133
212
  this.lineProgram = LineStripProgramCache.get(globe);
134
- const bufferManagersMap = new Map([
213
+ this._frameCounterTrigger = new FrameCounterTrigger(globe, 10, 1000, (globeChanges) => {
214
+ if (this._freed)
215
+ return;
216
+ this.__build(globeChanges);
217
+ globe.DrawRender();
218
+ });
219
+ this.__updateLODRelatedParameters();
220
+ this.__updateAdaptiveOpacityMultiplier();
221
+ const bufferManagerMap = new Map([
135
222
  ["position2d", {
136
223
  bufferManager: new BufferManager(globe.gl, 360 * 2 * 3, // plus 1 to cut
137
224
  { bufferType: this._options.bufferType, initialCapacity: initialCapacity }),
@@ -143,19 +230,19 @@ export class Padding1DegreePlugin {
143
230
  this._float32Array.fill(NaN); // reset the float32Array
144
231
  }
145
232
  for (let i = 0; i < 360; i++) {
146
- const startCoords = paddingInput.startCoords[i];
147
- const endCoords = paddingInput.endCoords[i];
148
- if (startCoords === null || endCoords === null) {
233
+ const outerCoords = paddingInput.outerCoords[i];
234
+ const innerCoords = paddingInput.innerCoords[i];
235
+ if (outerCoords === null || innerCoords === null) {
149
236
  continue;
150
237
  }
151
- let coords = globe.api_GetMercator2DPoint(startCoords[0], startCoords[1]);
238
+ let coordsOuter = globe.api_GetMercator2DPoint(outerCoords[0], outerCoords[1]);
152
239
  // fill the second coordinate with 0
153
- this._float32Array[i * 6] = coords[0];
154
- this._float32Array[i * 6 + 1] = coords[1];
155
- let innerCoords = globe.api_GetMercator2DPoint(endCoords[0], endCoords[1]);
240
+ this._float32Array[i * 6] = coordsOuter[0];
241
+ this._float32Array[i * 6 + 1] = coordsOuter[1];
242
+ let coordsInner = globe.api_GetMercator2DPoint(innerCoords[0], innerCoords[1]);
156
243
  // fill the second coordinate with 0
157
- this._float32Array[i * 6 + 2] = innerCoords[0];
158
- this._float32Array[i * 6 + 3] = innerCoords[1];
244
+ this._float32Array[i * 6 + 2] = coordsInner[0];
245
+ this._float32Array[i * 6 + 3] = coordsInner[1];
159
246
  }
160
247
  return this._float32Array.subarray(0, 360 * 2 * 3);
161
248
  }
@@ -174,22 +261,22 @@ export class Padding1DegreePlugin {
174
261
  }
175
262
  const _float32Array = this._float32Array;
176
263
  for (let i = 0; i < 360; i++) {
177
- const startCoords = paddingInput.startCoords[i];
178
- const endCoords = paddingInput.endCoords[i];
179
- if (startCoords === null || endCoords === null) {
264
+ const outerCoords = paddingInput.outerCoords[i];
265
+ const innerCoords = paddingInput.innerCoords[i];
266
+ if (outerCoords === null || innerCoords === null) {
180
267
  continue;
181
268
  }
182
269
  const height = paddingInput.heightFromGroundIn3D ?? this._options.defaultHeightFromGroundIn3D;
183
- let coords = globe.api_GetCartesian3DPoint(startCoords[0], startCoords[1], height, this._options.isMSL);
270
+ let coords = globe.api_GetCartesian3DPoint(outerCoords[0], outerCoords[1], height, this._options.isMSL);
184
271
  // fill the second coordinate with 0
185
272
  _float32Array[i * 9] = coords[0];
186
273
  _float32Array[i * 9 + 1] = coords[1];
187
274
  _float32Array[i * 9 + 2] = coords[2];
188
- let innerCoords = globe.api_GetCartesian3DPoint(endCoords[0], endCoords[1], height, this._options.isMSL);
275
+ let coordsInner = globe.api_GetCartesian3DPoint(innerCoords[0], innerCoords[1], height, this._options.isMSL);
189
276
  // fill the second coordinate with 0
190
- _float32Array[i * 9 + 3] = innerCoords[0];
191
- _float32Array[i * 9 + 4] = innerCoords[1];
192
- _float32Array[i * 9 + 5] = innerCoords[2];
277
+ _float32Array[i * 9 + 3] = coordsInner[0];
278
+ _float32Array[i * 9 + 4] = coordsInner[1];
279
+ _float32Array[i * 9 + 5] = coordsInner[2];
193
280
  }
194
281
  return _float32Array.subarray(0, 360 * 3 * 3);
195
282
  }
@@ -197,7 +284,7 @@ export class Padding1DegreePlugin {
197
284
  ],
198
285
  ]);
199
286
  if (this._options.variativeColorsOn) {
200
- bufferManagersMap.set("color", {
287
+ bufferManagerMap.set("color", {
201
288
  bufferManager: new BufferManager(globe.gl, 360 * 4 * 3, // 4 for RGBA
202
289
  { bufferType: this._options.bufferType, initialCapacity: initialCapacity }),
203
290
  adaptor: (paddingInput) => {
@@ -215,11 +302,11 @@ export class Padding1DegreePlugin {
215
302
  this._float32Array[i * 12] = color[0];
216
303
  this._float32Array[i * 12 + 1] = color[1];
217
304
  this._float32Array[i * 12 + 2] = color[2];
218
- this._float32Array[i * 12 + 3] = color[3] * this._opacityLODCoef;
305
+ this._float32Array[i * 12 + 3] = color[3];
219
306
  this._float32Array[i * 12 + 4] = color[0];
220
307
  this._float32Array[i * 12 + 5] = color[1];
221
308
  this._float32Array[i * 12 + 6] = color[2];
222
- this._float32Array[i * 12 + 7] = 0; //color[3] * this._opacityLODCoef;
309
+ this._float32Array[i * 12 + 7] = 0; //color[3] ;
223
310
  }
224
311
  return this._float32Array.subarray(0, 360 * 4 * 3);
225
312
  }
@@ -233,11 +320,11 @@ export class Padding1DegreePlugin {
233
320
  this._float32Array[i * 12] = color[0];
234
321
  this._float32Array[i * 12 + 1] = color[1];
235
322
  this._float32Array[i * 12 + 2] = color[2];
236
- this._float32Array[i * 12 + 3] = color[3] * this._opacityLODCoef;
323
+ this._float32Array[i * 12 + 3] = color[3];
237
324
  this._float32Array[i * 12 + 4] = color[0];
238
325
  this._float32Array[i * 12 + 5] = color[1];
239
326
  this._float32Array[i * 12 + 6] = color[2];
240
- this._float32Array[i * 12 + 7] = 0; // color[3] * this._opacityLODCoef;
327
+ this._float32Array[i * 12 + 7] = 0.1; // color[3];
241
328
  i++;
242
329
  }
243
330
  }
@@ -247,7 +334,7 @@ export class Padding1DegreePlugin {
247
334
  });
248
335
  }
249
336
  const vaoInput = ["position3d", "position2d", "color"].map((name) => {
250
- const bufferManager = bufferManagersMap.get(name);
337
+ const bufferManager = bufferManagerMap.get(name);
251
338
  if (!bufferManager) {
252
339
  return null;
253
340
  }
@@ -258,8 +345,8 @@ export class Padding1DegreePlugin {
258
345
  };
259
346
  });
260
347
  this._vao = this.lineProgram.createVAO(vaoInput[0], vaoInput[1], vaoInput[2]);
261
- this.bufferManagersMap = bufferManagersMap;
262
- this.bufferOrchestrator.resetWithCapacity(bufferManagersMap, initialCapacity);
348
+ this.bufferManagerMap = bufferManagerMap;
349
+ this.bufferOrchestrator.resetWithCapacity(bufferManagerMap, initialCapacity);
263
350
  this._uboHandler = this.lineProgram.createUBO("STATIC_DRAW");
264
351
  this._uboHandler.updateSingle("u_color", new Float32Array(this._options.defaultColor));
265
352
  }
@@ -272,6 +359,8 @@ export class Padding1DegreePlugin {
272
359
  console.warn("Globe or LineProgram or VAO is not initialized, cannot draw");
273
360
  return;
274
361
  }
362
+ this._frameCounterTrigger?.trigger();
363
+ // this.__build();
275
364
  const gl = this.globe.gl;
276
365
  const drawOptions = {
277
366
  drawRange: {
@@ -280,7 +369,7 @@ export class Padding1DegreePlugin {
280
369
  },
281
370
  };
282
371
  gl.disable(gl.DEPTH_TEST);
283
- this.lineProgram.draw(this._vao, drawOptions, this._pluginOpacity, this._uboHandler);
372
+ this.lineProgram.draw(this._vao, drawOptions, this._userOpacity * this._adaptiveOpacityMultiplier, this._uboHandler);
284
373
  gl.enable(gl.DEPTH_TEST);
285
374
  }
286
375
  free() {
@@ -293,6 +382,7 @@ export class Padding1DegreePlugin {
293
382
  return;
294
383
  }
295
384
  this._freed = true;
385
+ this._frameCounterTrigger?.free();
296
386
  LineStripProgramCache.release(this.lineProgram);
297
387
  this.lineProgram = null;
298
388
  this._uboHandler?.free();
@@ -300,58 +390,149 @@ export class Padding1DegreePlugin {
300
390
  this.globe.gl.deleteVertexArray(this._vao);
301
391
  this.globe = null;
302
392
  this._vao = null;
303
- this.bufferManagersMap.forEach((bufferManager) => {
393
+ this.bufferManagerMap.forEach((bufferManager) => {
304
394
  bufferManager.bufferManager.free();
305
395
  });
306
396
  this._float32Array = null;
307
397
  }
398
+ _buildPaddings(level, subSetIDs = null) {
399
+ if (level === "input") {
400
+ this.__inner(subSetIDs);
401
+ this.__elevation(subSetIDs);
402
+ }
403
+ else if (level === "innerCircle") {
404
+ // Build inner circle paddings
405
+ if (this._options.adativePaddingSize) {
406
+ this.__innerCircle(subSetIDs);
407
+ }
408
+ this.__elevation(subSetIDs);
409
+ }
410
+ else if (level === "elevation") {
411
+ // Build elevation paddings
412
+ this.__elevation(subSetIDs);
413
+ }
414
+ }
415
+ __inner(subSetIDs = null) {
416
+ // Implement inner circle padding logic
417
+ console.log("innerCircle Level Update");
418
+ const datas = this._dataMap;
419
+ let keys;
420
+ if (subSetIDs) {
421
+ keys = subSetIDs;
422
+ }
423
+ else {
424
+ keys = Array.from(datas.keys());
425
+ }
426
+ for (const key of keys) {
427
+ const value = datas.get(key);
428
+ if (!value)
429
+ continue;
430
+ // Implement inner circle padding logic using key and value
431
+ const { innerCoords, outerCoords } = preAdapter(this.globe, value, this._innerPaddingRatio, null);
432
+ value.outerCoords = outerCoords;
433
+ value.innerCoords = innerCoords;
434
+ }
435
+ }
436
+ __innerCircle(subSetIDs = null) {
437
+ // Implement inner circle padding logic
438
+ console.log("innerCircle Level Update");
439
+ const datas = this._dataMap;
440
+ let keys;
441
+ if (subSetIDs) {
442
+ keys = subSetIDs;
443
+ }
444
+ else {
445
+ keys = Array.from(datas.keys());
446
+ }
447
+ for (const key of keys) {
448
+ const value = datas.get(key);
449
+ if (!value)
450
+ continue;
451
+ // Implement inner circle padding logic using key and value
452
+ const { innerCoords } = preAdapter(this.globe, value, this._innerPaddingRatio, value.outerCoords);
453
+ value.innerCoords = innerCoords;
454
+ }
455
+ }
456
+ __elevation(subSetIDs = null) {
457
+ this.__updateAdaptiveOpacityMultiplier();
458
+ const bufferToUpdate = [this.globe?.api_GetCurrentGeometry() === 1 ? "position2d" : "position3d"];
459
+ const datas = this._dataMap;
460
+ const wrapper = [null];
461
+ this._float32Array = new Float32Array(360 * 4 * 4); // largest float32Array
462
+ let keys;
463
+ if (subSetIDs) {
464
+ keys = subSetIDs;
465
+ }
466
+ else {
467
+ keys = Array.from(datas.keys());
468
+ }
469
+ for (const key of keys) {
470
+ const value = datas.get(key);
471
+ if (!value)
472
+ continue;
473
+ wrapper[0] = value;
474
+ this.bufferOrchestrator.updateBulk(wrapper, this.bufferManagerMap, bufferToUpdate);
475
+ }
476
+ this._float32Array = null; // reset the float32Array
477
+ }
478
+ __build(globeChanges) {
479
+ if (globeChanges.lod) {
480
+ this.__updateLODRelatedParameters();
481
+ this._buildPaddings("innerCircle");
482
+ }
483
+ else if (globeChanges.look || globeChanges.geometry) {
484
+ this._buildPaddings("elevation");
485
+ }
486
+ }
308
487
  __updateLODRelatedParameters() {
309
488
  const lod = this.globe?.api_GetCurrentLODWithDecimal();
310
489
  this._innerPaddingRatio = 1 - Math.pow(0.7, lod);
311
490
  }
312
- _buildPaddings(level) {
313
- }
314
- __onCamOrLodChange() {
315
- //TODO: implement -> on lod change the _innerPaddingRatio and all positions should be recalculated.
316
- // calculation
317
- // if cam change, recalculate 3d positions
491
+ __updateAdaptiveOpacityMultiplier() {
492
+ if (this._options.adaptiveOpacity === true) {
493
+ const currentLod = this.globe?.api_GetCurrentLODWithDecimal();
494
+ this._adaptiveOpacityMultiplier = Math.max(1 - (2.9 / currentLod), 0.1);
495
+ }
496
+ else {
497
+ this._adaptiveOpacityMultiplier = 1; // TODO: set this once on adaptiveOpacity is Set to false
498
+ }
318
499
  }
319
500
  }
320
- function preAdapter(globe, paddingInput, paddingRatio, startCoords) {
321
- const endCoords = new Array(360);
322
- if (startCoords === null) {
323
- startCoords = new Array(360);
501
+ function preAdapter(globe, paddingInput, paddingRatio, outerCoords) {
502
+ const innerCoords = new Array(360);
503
+ if (outerCoords === null) {
504
+ outerCoords = new Array(360);
324
505
  for (let i = 0; i < 360; i++) {
325
506
  const { long, lat } = globe.Math.FindPointByPolar(paddingInput.center[0], // center long
326
507
  paddingInput.center[1], // center lat
327
- paddingInput.outerRadius, // outer radius
508
+ paddingInput.radius, // outer radius
328
509
  i);
329
510
  const { long: endLong, lat: endLat } = globe.Math.FindPointByPolar(paddingInput.center[0], // center long
330
511
  paddingInput.center[1], // center lat
331
- paddingInput.outerRadius * paddingRatio, // inner radius
512
+ paddingInput.radius * paddingRatio, // inner radius
332
513
  i);
333
514
  const longDifference = Math.abs(long - endLong);
334
515
  const latDifference = Math.abs(lat - endLat);
335
516
  if (longDifference > 45) {
336
- startCoords[i] = null;
337
- endCoords[i] = null;
517
+ outerCoords[i] = null;
518
+ innerCoords[i] = null;
338
519
  continue;
339
520
  }
340
521
  // Assign the calculated coordinates
341
- startCoords[i] = [long, lat];
342
- endCoords[i] = [endLong, endLat];
522
+ outerCoords[i] = [long, lat];
523
+ innerCoords[i] = [endLong, endLat];
343
524
  }
344
525
  }
345
526
  else {
346
- // Handle case when startCoords is provided
527
+ // Handle case when outerCoords is provided
347
528
  for (let i = 0; i < 360; i++) {
348
- if (startCoords[i] === null) {
349
- endCoords[i] = null;
529
+ if (outerCoords[i] === null) {
530
+ innerCoords[i] = null;
350
531
  continue;
351
532
  }
352
- const { long: endLong, lat: endLat } = globe.Math.FindPointByPolar(paddingInput.center[0], paddingInput.center[1], paddingInput.outerRadius * paddingRatio, i);
353
- endCoords[i] = [endLong, endLat];
533
+ const { long: endLong, lat: endLat } = globe.Math.FindPointByPolar(paddingInput.center[0], paddingInput.center[1], paddingInput.radius * paddingRatio, i);
534
+ innerCoords[i] = [endLong, endLat];
354
535
  }
355
536
  }
356
- return { startCoords, endCoords };
537
+ return { outerCoords, innerCoords };
357
538
  }
@@ -188,7 +188,7 @@ export class BufferOrchestrator {
188
188
  offsets.push(offset);
189
189
  }
190
190
  else {
191
- throw new Error("updateBulk item Key does not exist");
191
+ throw new Error(`updateBulk item Key does not exist, cannot update: ${item.key}`);
192
192
  }
193
193
  }
194
194
  if (bufferKeys) {
@@ -9,21 +9,31 @@ export class StaticDynamicStrategy {
9
9
  _staticDynamicState = StaticDynamicState.DYNAMIC;
10
10
  _transitionLevel = 8; // Default transition level
11
11
  _lastStaticDynamicState = StaticDynamicState.STATIC;
12
- constructor(globe, transitionLevel = 8) {
12
+ _lastGeometry = null;
13
+ _toStatic;
14
+ constructor(globe, transitionLevel = 8, toStatic) {
13
15
  this.globe = globe;
14
16
  this._transitionLevel = transitionLevel;
17
+ this._toStatic = toStatic;
15
18
  this.updateState();
16
19
  }
17
20
  updateState() {
18
21
  const currentLOD = this.globe.api_GetCurrentLODWithDecimal();
19
22
  const state = currentLOD < this._transitionLevel ? StaticDynamicState.STATIC : StaticDynamicState.DYNAMIC;
23
+ const currentGeometry = this.globe.api_GetCurrentGeometry();
20
24
  if (this._lastStaticDynamicState === StaticDynamicState.DYNAMIC && state === StaticDynamicState.STATIC) {
21
25
  this._staticDynamicState = StaticDynamicState.TO_STATIC;
26
+ this._toStatic();
27
+ }
28
+ else if ((currentGeometry !== this._lastGeometry) && state === StaticDynamicState.STATIC) {
29
+ this._staticDynamicState = StaticDynamicState.TO_STATIC;
30
+ this._toStatic();
22
31
  }
23
32
  else {
24
33
  this._staticDynamicState = state;
25
34
  }
26
35
  this._lastStaticDynamicState = this._staticDynamicState;
36
+ this._lastGeometry = currentGeometry;
27
37
  }
28
38
  getState() {
29
39
  return this._staticDynamicState;
@@ -0,0 +1,84 @@
1
+ import { CameraUniformBlockTotemCache } from "../programs/totems/camerauniformblock";
2
+ export class FrameCounterTrigger {
3
+ globe;
4
+ count = 0;
5
+ threshold;
6
+ timeoutMs;
7
+ timeoutId = null;
8
+ accumulatedChanges = {
9
+ geometry: false,
10
+ look: false,
11
+ lod: false,
12
+ lod2DWheel: false,
13
+ elevationScale: false,
14
+ screenMoved: false
15
+ };
16
+ cameraBlockTotem;
17
+ updateCallback;
18
+ constructor(globe, threshold, timeoutMs, updateCallback) {
19
+ this.threshold = threshold;
20
+ this.timeoutMs = timeoutMs;
21
+ this.updateCallback = updateCallback;
22
+ this.globe = globe;
23
+ this.cameraBlockTotem = CameraUniformBlockTotemCache.get(globe);
24
+ }
25
+ trigger(level = null) {
26
+ const globeChanges = this.cameraBlockTotem.getGlobeChanges();
27
+ if (!globeChanges.screenMoved)
28
+ return;
29
+ this.setChanges(globeChanges);
30
+ if (globeChanges.geometry || globeChanges.elevationScale || globeChanges.lod2DWheel) {
31
+ this.triggerUpdate();
32
+ return;
33
+ }
34
+ this.count++;
35
+ if (this.count === 1) {
36
+ this.startTimeout();
37
+ }
38
+ if (this.count >= this.threshold) {
39
+ this.triggerUpdate();
40
+ }
41
+ }
42
+ startTimeout() {
43
+ this.clearTimeout();
44
+ this.timeoutId = setTimeout(() => {
45
+ this.triggerUpdate();
46
+ }, this.timeoutMs);
47
+ }
48
+ triggerUpdate() {
49
+ this.clearTimeout();
50
+ this.updateCallback(this.accumulatedChanges);
51
+ this.reset();
52
+ }
53
+ clearTimeout() {
54
+ if (this.timeoutId) {
55
+ clearTimeout(this.timeoutId);
56
+ this.timeoutId = null;
57
+ }
58
+ }
59
+ setChanges(changes) {
60
+ // accumulate true states until reset
61
+ this.accumulatedChanges.geometry = this.accumulatedChanges.geometry || changes.geometry;
62
+ this.accumulatedChanges.look = this.accumulatedChanges.look || changes.look;
63
+ this.accumulatedChanges.lod = this.accumulatedChanges.lod || changes.lod;
64
+ this.accumulatedChanges.elevationScale = this.accumulatedChanges.elevationScale || changes.elevationScale;
65
+ this.accumulatedChanges.screenMoved = this.accumulatedChanges.screenMoved || changes.screenMoved;
66
+ this.accumulatedChanges.lod2DWheel = this.accumulatedChanges.lod2DWheel || changes.lod2DWheel;
67
+ }
68
+ getLevel() {
69
+ return this.accumulatedChanges;
70
+ }
71
+ reset() {
72
+ this.count = 0;
73
+ this.accumulatedChanges.geometry = false;
74
+ this.accumulatedChanges.look = false;
75
+ this.accumulatedChanges.lod = false;
76
+ this.accumulatedChanges.lod2DWheel = false;
77
+ this.accumulatedChanges.elevationScale = false;
78
+ this.accumulatedChanges.screenMoved = false;
79
+ this.clearTimeout();
80
+ }
81
+ free() {
82
+ CameraUniformBlockTotemCache.release(this.globe);
83
+ }
84
+ }
@@ -30,3 +30,26 @@ export default function imageToMagnitude(imageData) {
30
30
  }
31
31
  return magnitudeArray;
32
32
  }
33
+ export function imageToRadianAngle(imageData) {
34
+ const { image, uMax, vMax, uMin, vMin, height, width } = imageData;
35
+ const canvas = document.createElement('canvas');
36
+ const ctx = canvas.getContext('2d');
37
+ canvas.width = width;
38
+ canvas.height = height;
39
+ ctx.drawImage(image, 0, 0, width, height);
40
+ const img = ctx.getImageData(0, 0, width, height);
41
+ const data = img.data;
42
+ const angleArray = new Float32Array(height * width);
43
+ const uDiff = uMax - uMin;
44
+ const vDiff = vMax - vMin;
45
+ for (let i = 0; i < data.length; i += 4) {
46
+ const r = data[i];
47
+ const g = data[i + 1];
48
+ const u = uMin + (uDiff * r) / 255;
49
+ const v = vMin + (vDiff * g) / 255;
50
+ const angle = Math.atan2(v, u);
51
+ const index = i / 4;
52
+ angleArray[index] = angle;
53
+ }
54
+ return angleArray;
55
+ }
package/wind/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import WindPlugin from "./plugin";
2
2
  import createVectorFieldImage from "./vectorfieldimage";
3
- import imageToMagnitude from "./imagetovectorfieldandmagnitude";
3
+ import imageToMagnitude, { imageToRadianAngle } from "./imagetovectorfieldandmagnitude";
4
4
  import { createImageFromBase64 } from "../util/webglobjectbuilders";
5
- export { createVectorFieldImage, imageToMagnitude, WindPlugin, createImageFromBase64 };
5
+ export { createVectorFieldImage, imageToMagnitude, WindPlugin, createImageFromBase64, imageToRadianAngle };