@pirireis/webglobeplugins 0.8.5 → 0.8.7

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 (61) hide show
  1. package/bearing-line/plugin.js +51 -43
  2. package/circle-line-chain/plugin.js +52 -44
  3. package/compass-rose/compass-rose-padding-flat.js +3 -0
  4. package/compassrose/compassrose.js +1 -8
  5. package/heatwave/isobar/plugin.js +4 -1
  6. package/heatwave/isobar/quadtreecontours.js +0 -2
  7. package/heatwave/plugins/heatwaveglobeshell.js +2 -0
  8. package/package.json +1 -1
  9. package/partialrings/goals.md +2 -0
  10. package/partialrings/plugin.js +2 -1
  11. package/point-glow-line-to-earth/draw-subset-obj.js +27 -0
  12. package/point-glow-line-to-earth/keymethod.js +0 -0
  13. package/point-glow-line-to-earth/plugin.js +439 -0
  14. package/point-glow-line-to-earth/types.js +26 -0
  15. package/point-heat-map/index.js +0 -3
  16. package/point-heat-map/plugin-webworker.js +4 -9
  17. package/point-heat-map/point-to-heat-map-flow.js +0 -6
  18. package/point-tracks/plugin.js +42 -17
  19. package/programs/arrowfield/logic.js +6 -4
  20. package/programs/arrowfield/object.js +1 -1
  21. package/programs/float2legendwithratio/object.js +5 -4
  22. package/programs/globe-util/is-globe-moved.js +27 -0
  23. package/programs/globeshell/wiggle/logic.js +3 -7
  24. package/programs/globeshell/wiggle/object.js +1 -2
  25. package/programs/line-on-globe/circle-accurate-3d.js +16 -23
  26. package/programs/line-on-globe/circle-accurate-flat.js +21 -21
  27. package/programs/line-on-globe/lines-color-instanced-flat.js +6 -7
  28. package/programs/line-on-globe/naive-accurate-flexible.js +239 -0
  29. package/programs/line-on-globe/to-the-surface.js +129 -0
  30. package/programs/picking/pickable-renderer.js +216 -0
  31. package/programs/point-on-globe/element-globe-surface-glow.js +168 -0
  32. package/programs/point-on-globe/element-point-glow.js +184 -0
  33. package/programs/point-on-globe/square-pixel-point.js +8 -7
  34. package/programs/programcache.js +9 -0
  35. package/programs/rings/partial-ring/piece-of-pie.js +1 -1
  36. package/programs/totems/camerauniformblock.js +23 -2
  37. package/rangerings/plugin.js +9 -6
  38. package/shaders/fragment-toy/firework.js +55 -0
  39. package/shaders/fragment-toy/singularity.js +59 -0
  40. package/types.js +16 -0
  41. package/util/account/single-attribute-buffer-management/buffer-manager.js +2 -6
  42. package/util/account/util.js +17 -7
  43. package/util/check/typecheck.js +11 -0
  44. package/util/gl-util/buffer/integrate-buffer.js +74 -0
  45. package/util/gl-util/draw-options/client.js +59 -0
  46. package/util/gl-util/draw-options/methods.js +46 -0
  47. package/util/gl-util/draw-options/types.js +18 -0
  48. package/util/gl-util/uniform-block/manager.js +176 -0
  49. package/util/gl-util/uniform-block/roadmap.md +70 -0
  50. package/util/gl-util/uniform-block/shader.js +0 -0
  51. package/util/gl-util/uniform-block/types.js +7 -0
  52. package/util/jshelpers/equality.js +17 -0
  53. package/util/picking/picker-displayer.js +1 -1
  54. package/util/programs/shapesonglobe.js +17 -19
  55. package/util/shaderfunctions/geometrytransformations.js +27 -63
  56. package/bearing-line/roadmap.md +0 -15
  57. package/point-heat-map/plugin.js +0 -132
  58. package/programs/line-on-globe/naive-accurate.js +0 -221
  59. package/programs/line-on-globe/to-the-origin.js +0 -164
  60. package/util/jshelpers/timemethods.js +0 -19
  61. /package/{programs/point-on-globe/element-draw-glow.js → point-glow-line-to-earth/adaptors.js} +0 -0
@@ -0,0 +1,176 @@
1
+ import "./types";
2
+
3
+ const typeSizes = {
4
+ 'float': 4,
5
+ 'vec2': 8,
6
+ 'vec3': 16, // vec3 takes up same space as vec4 due to alignment
7
+ 'vec4': 16,
8
+ 'mat2': 32, // 2 vec4s (16 * 2)
9
+ 'mat3': 48, // 3 vec4s (16 * 3)
10
+ 'mat4': 64, // 4 vec4s (16 * 4)
11
+ 'int': 4,
12
+ 'ivec2': 8,
13
+ 'ivec3': 16,
14
+ 'ivec4': 16,
15
+ 'bool': 4
16
+ };
17
+
18
+ const typeAlignments = {
19
+ 'float': 4,
20
+ 'vec2': 8,
21
+ 'vec3': 16,
22
+ 'vec4': 16,
23
+ 'mat2': 16, // aligns to vec4 boundary
24
+ 'mat3': 16, // aligns to vec4 boundary
25
+ 'mat4': 16, // aligns to vec4 boundary
26
+ 'int': 4,
27
+ 'ivec2': 8,
28
+ 'ivec3': 16,
29
+ 'ivec4': 16,
30
+ 'bool': 4
31
+ };
32
+
33
+
34
+ const typeArrayConstructors = {
35
+ 'float': Float32Array,
36
+ 'vec2': Float32Array,
37
+ 'vec3': Float32Array,
38
+ 'vec4': Float32Array,
39
+ 'mat2': Float32Array,
40
+ 'mat3': Float32Array,
41
+ 'mat4': Float32Array,
42
+ 'int': Int32Array,
43
+ 'ivec2': Int32Array,
44
+ 'ivec3': Int32Array,
45
+ 'ivec4': Int32Array,
46
+ 'bool': Float32Array
47
+ };
48
+
49
+
50
+ class UniformBlockManager {
51
+
52
+ /**
53
+ *
54
+ * @param {UniformBlockName} blockName
55
+ * @param {Array<UniformBlockMember} blockMembers
56
+ * @param {string} prefix usage name of block in the shader
57
+ */
58
+ constructor(blockName, blockMembers, bindingPoint, prefix = "") {
59
+ this.blockName = blockName;
60
+ this.blockMembers = blockMembers;
61
+ this.bindingPoint = bindingPoint;
62
+ this.prefix = prefix;
63
+ this.offsetMap = this.__create_LayoutSTD140_OffsetMap();
64
+ this.size = this.__calculateSize();
65
+ }
66
+
67
+
68
+
69
+ glslCode() {
70
+ let code = `layout(std140) uniform ${this.blockName} {`;
71
+ for (const member of this.blockMembers) {
72
+ const { name, type } = member;
73
+ code += `${type} ${this.prefix}${name};`;
74
+ }
75
+ if (this.prefix) {
76
+ code += `} ${this.prefix};`;
77
+ } else {
78
+ code += `};`;
79
+ }
80
+ return code;
81
+ }
82
+
83
+
84
+ createUBO(gl, bufferWriteType = "STATIC_DRAW") {
85
+ const ubo = gl.createBuffer();
86
+ gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
87
+ gl.bufferData(gl.UNIFORM_BUFFER, this.size, gl[bufferWriteType]);
88
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, 0, ubo);
89
+
90
+ for (const member of this.blockMembers) {
91
+ const { name, type, value = null } = member;;
92
+ const offset = this.offsetMap.get(name);
93
+ const data = (value === null) ? new typeArrayConstructors[type](typeSizes[type] / 4).fill(NaN) : value;
94
+ gl.bufferSubData(gl.UNIFORM_BUFFER, offset, data);
95
+ }
96
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
97
+
98
+ return { // TODO typedef this, encapsulate this in a class or something, ask ai
99
+ ubo,
100
+ update: this.updateUBO.bind(this, gl, ubo),
101
+ bind: this.bind.bind(this, gl, ubo),
102
+ unbind: this.unbind.bind(this, gl),
103
+ free: () => gl.deleteBuffer(ubo)
104
+ };
105
+ }
106
+
107
+
108
+ updateUBO(gl, ubo, nameValueMap) {
109
+ gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
110
+ for (const [name, value] of nameValueMap.entries()) {
111
+ const offset = this.offsetMap.get(name);
112
+ const type = this.blockMembers.find(member => member.name === name).type;
113
+ if (offset === undefined) {
114
+ throw new Error(`Uniform block member ${name} not found in offset map.`);
115
+ }
116
+ let data;
117
+ if (Array.isArray(value)) {
118
+ data = new typeArrayConstructors[type](value);
119
+ } else if (typeof value === 'number') {
120
+ data = new typeArrayConstructors[type]([value]);
121
+ } else if (value instanceof ArrayBuffer) {
122
+ data = new typeArrayConstructors[type](value);
123
+ } else if (ArrayBuffer.isView(value) && !(value instanceof DataView))
124
+ data = (typeof value === 'number') ? new typeArrayConstructors[type]([value]) : new typeArrayConstructors[type](value);
125
+ else {
126
+ throw new Error(`Unsupported value type for ${name}: ${typeof value}`);
127
+ }
128
+ gl.bufferSubData(gl.UNIFORM_BUFFER, offset, data);
129
+ }
130
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
131
+ }
132
+
133
+ // call this after linking the program
134
+ assignBindingPoint(gl, program) {
135
+ const blockIndex = gl.getUniformBlockIndex(program, this.blockName);
136
+ gl.uniformBlockBinding(program, blockIndex, this.bindingPoint);
137
+ }
138
+
139
+ // call this before drawing
140
+ bind(gl, ubo) {
141
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, this.bindingPoint, ubo);
142
+ }
143
+
144
+ // call this right after drawing
145
+ unbind(gl) {
146
+ gl.bindBufferBase(gl.UNIFORM_BUFFER, this.bindingPoint, null);
147
+ }
148
+
149
+
150
+ // implicit methods
151
+ __create_LayoutSTD140_OffsetMap() {
152
+ let offset = 0;
153
+ const offsetMap = new Map();
154
+ for (const member of this.blockMembers) {
155
+ const { name, type } = member;
156
+ const size = typeSizes[type];
157
+ const alignment = typeAlignments[type];
158
+ const padding = (alignment - (offset % alignment)) % alignment;
159
+ offset += padding;
160
+ offsetMap.set(name, offset);
161
+ offset += size;
162
+ }
163
+ return offsetMap;
164
+ }
165
+
166
+ // __create_LayoutSTD140_OffsetMap() should be called before this
167
+ __calculateSize() {
168
+ const lastOffset = Array.from(this.offsetMap.values()).pop();
169
+ const lastItemAlignment = typeAlignments[this.blockMembers[this.blockMembers.length - 1].type];
170
+ return lastOffset + lastItemAlignment;
171
+ }
172
+
173
+ }
174
+
175
+
176
+ export { UniformBlockManager };
@@ -0,0 +1,70 @@
1
+ # UniformBlock Wrapper
2
+
3
+ - Uniform shader string
4
+ - bind/unbind
5
+ - set/get uniform value generic
6
+
7
+ ## INPUT
8
+ - uniform block name
9
+ - Array<{type, name}> UniformBlockMembers
10
+
11
+
12
+ ## PROCESS
13
+
14
+ - Calculate and save starting offset of each member
15
+ - Create UBO
16
+ - Bind UBO
17
+ - Set uniform value
18
+
19
+ ### Calculate and save starting offset of each member
20
+
21
+ layout(std140) is a convention. The calculation should be done according to this convention.
22
+
23
+
24
+ type | size
25
+ --- | ---
26
+ float | 4
27
+ vec2 | 8
28
+ vec3 | 12
29
+ vec4 | 16
30
+ mat2 | 16
31
+ mat3 | 48
32
+ mat4 | 64
33
+
34
+ A line is 16 bytes aligned. Alignment can be shared if previous member is equal or bigger then the next member and the sum of the sizes are smaller then 16 bytes.
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+ ## setMethod
46
+
47
+ update({
48
+ color = null,
49
+ bboxOffsetRad = null,
50
+ bboxSizeRad = null,
51
+ resolution = null,
52
+ tailLengthRatio = null,
53
+ wingLengthRatio = null,
54
+ height = null,
55
+ opacity = null,
56
+ noDataValue = null,
57
+ } = {}) {
58
+ const { gl, ubo } = this;
59
+ gl.bindBuffer(gl.UNIFORM_BUFFER, ubo);
60
+ if (color !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 0, new Float32Array(color));
61
+ if (opacity !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 12, new Float32Array([opacity]));
62
+ if (bboxOffsetRad !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 16, new Float32Array(bboxOffsetRad));
63
+ if (bboxSizeRad !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 24, new Float32Array(bboxSizeRad));
64
+ if (resolution !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 32, new Float32Array(resolution));
65
+ if (tailLengthRatio !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 40, new Float32Array([tailLengthRatio]));
66
+ if (wingLengthRatio !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 44, new Float32Array([wingLengthRatio]));
67
+ if (height !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 48, new Float32Array([height]));
68
+ if (noDataValue !== null) gl.bufferSubData(gl.UNIFORM_BUFFER, 52, new Float32Array([noDataValue]));
69
+ gl.bindBuffer(gl.UNIFORM_BUFFER, null);
70
+ }
File without changes
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @typedef {string} UniformBlockName
3
+ *
4
+ * @typedef {string} GLSLType | mat4, mat3, vec4, vec3, vec2, float, int, bool
5
+ * @typedef {{name: string, type: GLSLType, null|Float32Array: value}} UniformBlockMember
6
+ *
7
+ */
@@ -0,0 +1,17 @@
1
+ function arraysEqual(a, b) {
2
+ if (a === b) return true;
3
+ if (a == null || b == null) return false;
4
+ if (a.length !== b.length) return false;
5
+
6
+ // If you don't care about the order of the elements inside
7
+ // the array, you should sort both arrays here.
8
+ // Please note that calling sort on an array will modify that array.
9
+ // you might want to clone your array first.
10
+
11
+ for (var i = 0; i < a.length; ++i) {
12
+ if (a[i] !== b[i]) return false;
13
+ }
14
+ return true;
15
+ }
16
+
17
+ export { arraysEqual };
@@ -31,7 +31,6 @@ class PickerDisplayer {
31
31
  width = this.globe.api_ScrW();
32
32
  height = this.globe.api_ScrH();
33
33
  }
34
- console.log("resize picker displayer", width, height);
35
34
  const { gl, colorTexture, indexTexture } = this;
36
35
 
37
36
  gl.deleteTexture(colorTexture);
@@ -97,6 +96,7 @@ class PickerDisplayer {
97
96
  }
98
97
 
99
98
 
99
+
100
100
  pickBbox(left, top, right, bottom, callback) {
101
101
  const size = (right - left) * (bottom - top) * 4;
102
102
  this._pick(size, left, top, right - left, bottom - top, callback);
@@ -1,4 +1,5 @@
1
1
  import { createProgram } from "../webglobjectbuilders";
2
+ import { CameraUniformBlockString, CameraUniformBlockTotemCache } from "../../programs/totems/camerauniformblock";
2
3
  import { shaderfunctions } from "..";
3
4
  /** TODO:
4
5
  * 3d icin calistir
@@ -51,19 +52,14 @@ export class ShapesOnGlobeProgram {
51
52
  }
52
53
 
53
54
  _createProgramWrapper() {
54
- const gl = this.gl;
55
+ const { gl, globe } = this;
55
56
  const vertexSource = `#version 300 es
56
57
  precision highp float;
58
+ ${CameraUniformBlockString}
57
59
 
58
60
  in vec2 a_position;
59
61
  in vec4 a_color;
60
62
 
61
- uniform mat4 u_model_view_matrix;
62
- uniform mat4 u_proj_matrix;
63
- uniform vec3 u_transpos;
64
-
65
- uniform vec2 u_mapWH;
66
- uniform vec2 u_scrWH;
67
63
 
68
64
  uniform bool u_is3D;
69
65
  uniform float height;
@@ -77,14 +73,13 @@ export class ShapesOnGlobeProgram {
77
73
 
78
74
 
79
75
  void main() {
80
- // vec3 pos = u_bbox_matrix * vec3(a_position, height);
81
76
  vec3 pos = vec3(a_position, height);
82
- if(u_is3D){
77
+ if(is3D){
83
78
  pos = pixelXYToCartesian3DPoint(pos);
84
- gl_Position = u_proj_matrix * u_model_view_matrix * vec4(pos - u_transpos, 1.0);
79
+ gl_Position = projection * view * vec4(pos - translate, 1.0);
85
80
  } else {
86
- vec2 xy = pixelXYToCartesian2DPoint(pos.xy, u_transpos.xy, u_mapWH, u_scrWH);
87
- gl_Position = u_proj_matrix * vec4(xy.x, xy.y, 0.0, 1.0);
81
+ vec2 xy = pixelXYToCartesian2DPoint(pos.xy, translate.xy, mapWH, screenWH);
82
+ gl_Position = projection * vec4(xy.x, xy.y, 0.0, 1.0);
88
83
  }
89
84
  gl_PointSize = u_point_size;
90
85
  v_color = a_color;
@@ -121,17 +116,18 @@ export class ShapesOnGlobeProgram {
121
116
  gl.vertexAttribPointer(a_color, 4, gl.FLOAT, false, 6 * 4, 2 * 4);
122
117
  gl.bindVertexArray(null);
123
118
 
119
+ const cm = CameraUniformBlockTotemCache.get(globe);
120
+ const bindingPoint = 0;
121
+ const cmIndex = gl.getUniformBlockIndex(program, "CameraUniformBlock");
122
+ gl.uniformBlockBinding(program, cmIndex, bindingPoint);
123
+
124
124
  return {
125
125
  program: program,
126
126
  vao: vao,
127
- u_model_view_matrix: gl.getUniformLocation(program, 'u_model_view_matrix'),
128
- u_proj_matrix: gl.getUniformLocation(program, 'u_proj_matrix'),
129
- u_transpos: gl.getUniformLocation(program, 'u_transpos'),
130
127
  u_point_size: gl.getUniformLocation(program, 'u_point_size'),
131
- u_mapWH: gl.getUniformLocation(program, 'u_mapWH'),
132
- u_scrWH: gl.getUniformLocation(program, 'u_scrWH'),
133
- u_is3D: gl.getUniformLocation(program, 'u_is3D'),
134
128
  u_opacity: gl.getUniformLocation(program, 'u_opacity'),
129
+ bindCamera: () => cm.bind(bindingPoint),
130
+ unbindCamera: () => cm.unbind(bindingPoint)
135
131
  };
136
132
  }
137
133
 
@@ -149,6 +145,7 @@ export class ShapesOnGlobeProgram {
149
145
  gl.uniformMatrix4fv(_programWrapper.u_proj_matrix, false, uProjectionMatrix);
150
146
  gl.uniform3f(_programWrapper.u_transpos, uTranslate.x, uTranslate.y, uTranslate.z);
151
147
  gl.bindVertexArray(_programWrapper.vao);
148
+ _programWrapper.bindCamera();
152
149
  if (!_is3D) {
153
150
  const mapWH = this.globe.api_GetCurrentWorldWH();
154
151
  gl.uniform2f(_programWrapper.u_mapWH, mapWH.width, mapWH.height);
@@ -157,8 +154,9 @@ export class ShapesOnGlobeProgram {
157
154
 
158
155
  for (const drawRange of drawRanges) {
159
156
  gl.drawArrays(this._drawMode, drawRange[0], drawRange[1]);
160
- gl.drawArrays(gl.POINTS, drawRange[0], 1);
157
+ // gl.drawArrays(gl.POINTS, drawRange[0], 1);
161
158
  }
159
+ _programWrapper.unbindCamera();
162
160
 
163
161
  gl.bindVertexArray(null);
164
162
  if (deepTest) {
@@ -192,26 +192,6 @@ vec2 circleLimpFromLongLatRadCenterMercatorCompass(vec2 center, float radius, fl
192
192
  } `;
193
193
 
194
194
 
195
- // Function to interpolate between two Cartesian points using spherical interpolation (slerp)
196
- export const slerp = `
197
- vec3 slerp(vec3 A, vec3 B, float t) {
198
- float cosTheta = dot(A, B);
199
- float theta = acos(clamp(cosTheta, -1.0, 1.0)); // Angle between the points
200
-
201
- float sinTheta = sin(theta);
202
-
203
- // Avoid division by zero // many points falls in to this category
204
- if (sinTheta < 0.00001) {
205
- return mix(A, B, t); // Linear interpolation as fallback
206
- }
207
-
208
- float factorA = sin((1.0 - t) * theta) / sinTheta;
209
- float factorB = sin(t * theta) / sinTheta;
210
-
211
- return factorA * A + factorB * B;
212
- }
213
- `;
214
-
215
195
  // Function to convert Cartesian coordinates back to spherical (latitude, longitude)
216
196
  export const cartesianToSpherical = `
217
197
  vec2 cartesianToSpherical(vec3 point) {
@@ -223,16 +203,6 @@ vec2 cartesianToSpherical(vec3 point) {
223
203
 
224
204
  // Main function to calculate an intermediate point
225
205
 
226
- export const interpolateGeographicPoint = slerp + cartesianToSpherical + longLatRadToCartesian3D + `
227
- vec3 interpolateGeographicPoint(vec2 start, vec2 end, float t) {
228
- vec3 pointA = longLatRadToCartesian3D(start);
229
- vec3 pointB = longLatRadToCartesian3D(end);
230
- vec3 interpolatedPoint = slerp(pointA, pointB, t);
231
- return interpolatedPoint;
232
- // return cartesianToSpherical(interpolatedPoint);
233
- }
234
- `;
235
-
236
206
 
237
207
 
238
208
  export const angleBetweenTwoPointsRadian = `
@@ -253,35 +223,7 @@ float circleCircumferenceInterPolationOf2PointsRadian(vec2 center, vec2 target,
253
223
  }
254
224
  `
255
225
 
256
- const circumferencePoints = `
257
- vec2 circumferencePoints(vec2 center, vec2 target, vec2 target2, float phase) {
258
- // Calculate vectors from center to target and target2
259
- vec2 v1 = target - center;
260
- vec2 v2 = target2 - center;
261
-
262
- // Normalize the vectors to ensure they are on the unit circle
263
- v1 = normalize(v1);
264
- v2 = normalize(v2);
265
-
266
- // Calculate the angle between the vectors
267
- float angle1 = atan(v1.y, v1.x);
268
- float angle2 = atan(v2.y, v2.x);
269
-
270
- // Ensure the angles are continuous (handle wrap-around at 2π)
271
- if (angle2 < angle1) {
272
- angle2 += 2.0 * 3.14159265359; // Add 2π to angle2 if it is smaller
273
- }
274
226
 
275
- // Interpolate the angle based on the phase
276
- float interpolatedAngle = mix(angle1, angle2, phase);
277
-
278
- // Calculate the new point on the circle
279
- vec2 result = vec2(cos(interpolatedAngle), sin(interpolatedAngle));
280
-
281
- // Scale back to the original circle radius and shift to center
282
- return center + length(target - center) * result;
283
- }
284
- `
285
227
 
286
228
 
287
229
  export const realDistanceOnSphereR1 = `
@@ -294,22 +236,44 @@ float realDistanceOnSphereR1(vec2 longLat1, vec2 longLat2) {
294
236
  }
295
237
  `;
296
238
 
297
- const pointsOnSphereBetween = `vec3 pointsOnSphereBetween(vec3 a, vec3 b, float ratio) {
239
+
240
+
241
+ const pointsOnSphereBetween = `
242
+ vec3 pointsOnSphereBetween(vec3 a, vec3 b, float ratio) {
298
243
  // Normalize the input points to ensure they are on the unit sphere
299
244
  a = normalize(a);
300
245
  b = normalize(b);
301
246
 
247
+ // Compute the dot product and clamp it to avoid numerical issues
248
+ float dotProduct = clamp(dot(a, b), -1.0, 1.0);
249
+
302
250
  // Compute the angle between the points
303
- float theta = acos(dot(a, b));
251
+ float theta = acos(dotProduct);
252
+
253
+ // Handle the edge case where the points are nearly identical
254
+ if (theta < 0.0001) {
255
+ return normalize(mix(a, b, ratio)); // Linear interpolation as fallback
256
+ }
304
257
 
305
258
  // Compute the interpolated point using spherical linear interpolation (slerp)
306
- vec3 result = (sin((1.0 - ratio) * theta) * a + sin(ratio * theta) * b) / sin(theta);
259
+ float sinTheta = sin(theta);
260
+ float factorA = sin((1.0 - ratio) * theta) / sinTheta;
261
+ float factorB = sin(ratio * theta) / sinTheta;
262
+
263
+ vec3 result = factorA * a + factorB * b;
307
264
 
308
265
  // Return the normalized result to ensure it lies on the sphere
309
266
  return normalize(result);
310
- }`
267
+ }`;
311
268
 
312
269
 
270
+ const slerp = `
271
+ ${pointsOnSphereBetween}
272
+ vec3 slerp(vec3 A, vec3 B, float t) {
273
+ return pointsOnSphereBetween(A, B, t) * mix(length(A), length(B), t);
274
+ }
275
+ `
276
+
313
277
  const circleLimpFromLongLatRadCenterCartesian3D_accurate = R + `
314
278
  vec3 circleLimpFromLongLatRadCenterCartesian3D_accurate( vec3 geoW, float radius, float angle) {
315
279
  vec3 normal = normalize(geoW);
@@ -357,7 +321,7 @@ vec2 circleLimpFromLongLatRadCenterMercatorRealDistanceNew_accurate(vec2 mercato
357
321
  }`;
358
322
 
359
323
  export {
360
- pointsOnSphereBetween,
324
+ slerp,
361
325
  circleLimpFromLongLatRadCenterCartesian3D_accurate,
362
326
  circleLimpFromLongLatRadCenterMercatorCompass_accurate,
363
327
  circleLimpFromLongLatRadCenterMercatorRealDistanceNew_accurate
@@ -1,15 +0,0 @@
1
- # Two problems:
2
- lines are curved to to arrive perpendicular to the longitude lines
3
- patrial rings are not fit to the lines nor the bearing angle
4
-
5
-
6
-
7
- # AngledLine
8
-
9
- Does not render
10
- Check:
11
- [-] VAO
12
- [-] Attributes are loaded with data
13
- Assign constants to attributes.
14
- [x] Uniforms are loaded // program was not used before setting opacity
15
- [x] Check geometry // Assigning a constant to the geometry made all edges of the line overlap and the line was not visible
@@ -1,132 +0,0 @@
1
- import { PointHeatmapFlow } from "./point-to-heat-map-flow";
2
- import { TimeTrackInterpolator } from "../util/interpolation/timetrack/timetrack-interpolator";
3
- import { createTexture, getColorRampModed } from "../util";
4
- // TODO: DEPRECATED
5
- class PointHeatmapPlugin {
6
-
7
- constructor(id, { opacity = 1.0, pointSize = 5.0 } = {}) {
8
- this.id = id;
9
- this.globe = null;
10
- this.gl = null;
11
- this.densityToLegendProgram = null;
12
- this._time = null;
13
-
14
-
15
- this._opacity = opacity;
16
- this._pointSize = pointSize;
17
- this._legendTexture = null;
18
- this.timeTrackInterpolator = new TimeTrackInterpolator();
19
- }
20
-
21
- // globe interaction
22
-
23
- init(globe, gl) {
24
- this.globe = globe;
25
- this.gl = gl;
26
- this.flow = new PointHeatmapFlow(globe);
27
- this.setGeometry();
28
- this.resize();
29
- }
30
-
31
-
32
- setPointSize(pointSize) {
33
- if (typeof pointSize !== 'number' || pointSize <= 0) {
34
- throw new Error('Invalid pointSize');
35
- }
36
- this._pointSize = pointSize;
37
- this.globe.DrawRender();
38
- }
39
-
40
-
41
- /**
42
- * @param {Array<string>}
43
- * @param {string} mode "interpolated" | "discrete"
44
- */
45
-
46
- setColorRamp(values, thresholds, mode = "interpolated") {
47
- const gl = this.gl
48
- if (this.gl === null) {
49
- throw new Error('Plugin not initialized');
50
- };
51
- const rampData = getColorRampModed(values, thresholds, mode);
52
- const texture = createTexture(gl, gl.LINEAR, rampData, 256, 1);
53
- if (this._legendTexture) {
54
- this.gl.deleteTexture(this._legendTexture);
55
- }
56
- this._legendTexture = texture;
57
- this.globe.DrawRender();
58
- }
59
-
60
-
61
- setTime(time) {
62
- this._time = time;
63
- const data = this.timeTrackInterpolator.interpolate(time);
64
- if (data === null) {
65
- return;
66
- }
67
- this.flow.setData(data);
68
- }
69
-
70
-
71
- setTimetracks(timeTracks) {
72
- this.timeTrackInterpolator.setTimetracks(timeTracks);
73
- if (this._time !== null) {
74
- this.setTime(this._time);
75
- }
76
- this.globe.DrawRender();
77
- }
78
-
79
-
80
- setOpacity(opacity) {
81
- if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {
82
- throw new Error('Invalid opacity');
83
- }
84
- this._opacity = opacity;
85
- this.globe.DrawRender();
86
- }
87
-
88
-
89
-
90
- setGeometry() {
91
- const geometry = this.globe.api_GetCurrentGeometry();
92
- this.timeTrackInterpolator.setGeometry(geometry);
93
- if (this._time !== null) {
94
- this.setTime(this._time);
95
- }
96
- }
97
-
98
-
99
- draw3D() {
100
- if (this.isReady()) {
101
- this.flow.draw(this._legendTexture, this._pointSize, this._opacity);
102
- }
103
- }
104
-
105
-
106
- resize() {
107
- this.timeTrackInterpolator.setGeometry(this.globe.api_GetCurrentGeometry());
108
- this.flow.resize();
109
- if (this._time !== null) {
110
- this.setTime(this._time);
111
- }
112
- }
113
-
114
-
115
- isReady() {
116
- return (this.gl !== null && this._legendTexture !== null);
117
- }
118
-
119
- free() {
120
- if (this._isFreed) return;
121
- this.gl.deleteTexture(this._legendTexture);
122
- this.flow.free();
123
- this.flow = null;
124
- this.gl = null;
125
- this._isFreed = true;
126
- this.timeTrackInterpolator = null;
127
- this._legendTexture = null;
128
- }
129
- }
130
-
131
-
132
- export { PointHeatmapPlugin };