@pirireis/webglobeplugins 0.6.48-a → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/Math/angle-calculation.js +4 -2
  2. package/Math/methods.js +197 -0
  3. package/package.json +1 -1
  4. package/point-heat-map/adaptors/timetracksplugin-format-to-this.js +78 -0
  5. package/point-heat-map/index.js +0 -0
  6. package/point-heat-map/plugin-webworker.js +162 -0
  7. package/point-heat-map/plugin.js +134 -0
  8. package/point-heat-map/point-to-heat-map-flow.js +155 -0
  9. package/point-heat-map/readme.md +15 -0
  10. package/programs/data2legend/density-to-legend.js +115 -0
  11. package/programs/data2legend/point-to-density-texture.js +114 -0
  12. package/programs/line-on-globe/degree-padding-around-circle-3d.js +4 -4
  13. package/rangerings/rangeringangletext.js +15 -16
  14. package/timetracks/adaptors-line-strip.js +1 -1
  15. package/timetracks/program-line-strip.js +1 -1
  16. package/timetracks/program.js +1 -1
  17. package/timetracks/programpoint-line-strip.js +1 -1
  18. package/timetracks/programpoint.js +1 -1
  19. package/timetracks/readme.md +1 -0
  20. package/util/algorithms/index.js +0 -0
  21. package/util/algorithms/search-binary.js +26 -0
  22. package/util/interpolation/index.js +0 -0
  23. package/util/interpolation/timetrack/index.js +0 -0
  24. package/util/interpolation/timetrack/timetrack-interpolator.js +89 -0
  25. package/util/interpolation/timetrack/web-worker.js +46 -0
  26. package/util/programs/draw-texture-on-canvas.js +103 -0
  27. package/util/programs/texturetoglobe.js +1 -1
  28. package/util/webglobe/gldefaultstates.js +2 -1
  29. package/waveparticles/plugin.js +0 -2
  30. package/wind/index.js +0 -2
  31. package/wind/plugin.js +1 -1
  32. package/write-text/context-text3.js +1 -1
@@ -1,4 +1,4 @@
1
- export function bearingRealAngle(long, lat, endLong, endLat) {
1
+ function bearingRealAngle(long, lat, endLong, endLat) {
2
2
  const rLong = Radians * long;
3
3
  const rLat = Radians * lat;
4
4
  const rEndLong = Radians * endLong;
@@ -9,4 +9,6 @@ export function bearingRealAngle(long, lat, endLong, endLat) {
9
9
  let initialBearing = Math.atan2(x, y) / Radians;
10
10
  initialBearing = (initialBearing + 360) % 360;
11
11
  return initialBearing;
12
- }
12
+ }
13
+
14
+ export { bearingRealAngle };
@@ -0,0 +1,197 @@
1
+
2
+ const WORLD_RADIUS_3D = 6371.137;
3
+ const WORLD_RADIUS_MERCATOR = 6371137;
4
+ const POLE = 20037508.34;
5
+
6
+ /**
7
+ * @typedef {Array<number>} vec3 [x, y, z]
8
+ * @typedef {Array<number>} vec2 [x, y]
9
+ * @typedef {Array<number>} vec4 [x, y, z, w]
10
+ * @typedef {number} fraction a number between 0 and 1
11
+ * @typedef {Array<number>} wgs84 [long, lat]
12
+ */
13
+
14
+ // *********************************************************
15
+ // **************** VECTOR OPERATIONS **********************
16
+ // *********************************************************
17
+ const RADIANS = Math.PI / 180;
18
+
19
+
20
+ /**
21
+ * @param {vec3} a
22
+ * @returns {vec3}
23
+ */
24
+ const normalize3 = (a) => {
25
+ const len = length3(a);
26
+ return [a[0] / len, a[1] / len, a[2] / len];
27
+ }
28
+
29
+
30
+ /**
31
+ * @param {vec3} a
32
+ * @param {vec3} b
33
+ * @returns {number}
34
+ */
35
+ const dot3 = (a, b) => {
36
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
37
+ }
38
+
39
+
40
+ /**
41
+ * @param {vec3} a
42
+ * @returns {number}
43
+ */
44
+ const length3 = (a) => {
45
+ return Math.sqrt(dot3(a, a));
46
+ }
47
+
48
+
49
+ // *********************************************************
50
+ // **************** TRANSFORMATIONS ************************
51
+ // *********************************************************
52
+
53
+ /**
54
+ * @param {vec3} cartesian
55
+ * @returns {vec2} long lat in radians
56
+ */
57
+ const cartesian3dToRadian = (cartesian) => {
58
+ const x = cartesian[0];
59
+ const y = cartesian[1];
60
+ const z = cartesian[2];
61
+ // const length = Math.sqrt(x * x + y * y + z * z);
62
+ const long = Math.atan2(y, x);
63
+ const lat = Math.asin(z)// length);
64
+ return [long, lat];
65
+ }
66
+
67
+
68
+ /**
69
+ * @param {vec2} xy long lat in radians
70
+ * @returns {vec2} long lat in mercator meters
71
+ */
72
+ const radianToMercator = (xy) => {
73
+ return [WORLD_RADIUS_MERCATOR * xy[0], WORLD_RADIUS_MERCATOR * Math.log(Math.tan(Math.PI / 4 + xy[1] / 2))];
74
+ }
75
+
76
+ /**
77
+ * @param {vec2} xy long lat radians
78
+ * @returns {vec3} cartesian
79
+ */
80
+
81
+ const radianToCartesian3d = (xy) => {
82
+ const x = Math.cos(xy[1]) * Math.cos(xy[0]);
83
+ const y = Math.cos(xy[1]) * Math.sin(xy[0]);
84
+ const z = -Math.sin(xy[1]);
85
+ return [x, y, z];
86
+ }
87
+
88
+
89
+ // *********************************************************
90
+ // ***************** INTERPOLATIONS ************************
91
+ // *********************************************************
92
+
93
+ /**
94
+ * @param {vec3} normalizedA
95
+ * @param {vec3} normalizedB
96
+ * @param {fraction} ratio
97
+ * @returns {vec3}
98
+ */
99
+ const sphericalLinearInterpolation_UnitVector = (normalizedA, normalizedB, ratio) => {
100
+ const theta = Math.acos(dot3(normalizedA, normalizedB));
101
+ if (theta < 0.000001) return normalizedA; // CALIBRATE?
102
+ const sinTheta = Math.sin(theta);
103
+ const result = [
104
+ (Math.sin((1.0 - ratio) * theta) * normalizedA[0] + Math.sin(ratio * theta) * normalizedB[0]) / sinTheta,
105
+ (Math.sin((1.0 - ratio) * theta) * normalizedA[1] + Math.sin(ratio * theta) * normalizedB[1]) / sinTheta,
106
+ (Math.sin((1.0 - ratio) * theta) * normalizedA[2] + Math.sin(ratio * theta) * normalizedB[2]) / sinTheta
107
+ ];
108
+ return result;
109
+ }
110
+
111
+
112
+ /**
113
+ * @param {vec3} normalizedA
114
+ * @param {vec3} normalizedB
115
+ * @param {fraction} ratio
116
+ * @returns
117
+ */
118
+ const sphericalLinearInterpolation_Mercator = (normalizedA, normalizedB, ratio) => {
119
+ const unitVector = sphericalLinearInterpolation_UnitVector(normalizedA, normalizedB, ratio);
120
+ const angles = cartesian3dToRadian(unitVector);
121
+ return radianToMercator(angles);
122
+ }
123
+
124
+ /**
125
+ * @param {vec4} a vec3 unit vector and length
126
+ * @param {vec4} b vec3 unit vector and length
127
+ * @param {fraction} ratio
128
+ */
129
+ const sphericalLinearInterpolation_Cartesian3d = (a, b, ratio) => {
130
+ const unitVector = sphericalLinearInterpolation_UnitVector(a, b, ratio);
131
+ const height = a[3] + (b[3] - a[3]) * ratio;
132
+ return [unitVector[0] * height, unitVector[1] * height, unitVector[2] * height];
133
+ }
134
+
135
+
136
+ /**
137
+ *
138
+ * @param {wgs84} coordinates
139
+ * @returns {vec3}
140
+ */
141
+ const wgs84ToUnitVector = (coordinates) => {
142
+ const long = coordinates[0] * RADIANS;
143
+ const lat = coordinates[1] * RADIANS;
144
+
145
+ const x = Math.cos(lat) * Math.cos(long);
146
+ const y = Math.cos(lat) * Math.sin(long);
147
+ const z = Math.sin(lat);
148
+ return [x, y, z];
149
+ }
150
+
151
+
152
+ /**
153
+ * @param {vec3} cartesian
154
+ * @returns {vec4} unit vector and length
155
+ */
156
+ const cartesian3dToUnitVectorWithHeight = (cartesian) => {
157
+ const x = cartesian[0];
158
+ const y = cartesian[1];
159
+ const z = cartesian[2];
160
+ const height = Math.sqrt(x * x + y * y + z * z);
161
+ return [x / height, y / height, z / height, height];
162
+ }
163
+
164
+ /**
165
+ * @param {vec2} pixelXY
166
+ * @returns {vec2} long lat in radians
167
+ */
168
+
169
+ const pixelXYToRadians = (pixelXY) => {
170
+ const long = (2.0 * pixelXY[0] - 1.0) * Math.PI;
171
+ const lat = (2.0 * pixelXY[1] - 1.0) * Math.PI / 2.0;
172
+ return [long, lat]
173
+ }
174
+
175
+ const pixelXYLenghtToUnitVectorWithHeight = (pixelXYHeight) => {
176
+ const [long, lat] = pixelXYToRadians(pixelXYHeight);
177
+ const radius = WORLD_RADIUS_3D + pixelXYHeight[2];
178
+ return radianToCartesian3d([long, lat]).concat(radius);
179
+ }
180
+
181
+ export {
182
+ RADIANS,
183
+ WORLD_RADIUS_3D,
184
+ normalize3,
185
+ dot3,
186
+ length3,
187
+ cartesian3dToRadian,
188
+ radianToMercator,
189
+ radianToCartesian3d,
190
+ sphericalLinearInterpolation_UnitVector,
191
+ sphericalLinearInterpolation_Mercator,
192
+ sphericalLinearInterpolation_Cartesian3d,
193
+ wgs84ToUnitVector,
194
+ cartesian3dToUnitVectorWithHeight,
195
+ pixelXYLenghtToUnitVectorWithHeight
196
+ }
197
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pirireis/webglobeplugins",
3
- "version": "0.6.48-a",
3
+ "version": "0.7.0",
4
4
  "main": "index.js",
5
5
  "author": "Toprak Nihat Deniz Ozturk",
6
6
  "license": "MIT"
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @typedef {Float32Array} TimeTrackMultiColorData | A linestring is representation, let A{a1, a2, a3}, B{b1, b2} be the points of the line.
3
+ * TimeTrackMultiColorData is [
4
+ * a1x, a1y, a1z, a1time, a1r, a1g, a1b, a1time, a3time,
5
+ * a2x, a2y, a2z, a2time, a2r, a2g, a2b, a1time, a3time,
6
+ * a3x, a3y, a3z, a3time, a3r, a3g, a3b, a1time, a3time,
7
+ * 0, 0, 0, 0, -1, -1, -1, 0, 0,
8
+ * b1x, b1y, b1z, b1time, b1r, b1g, b1b, b1time, b2time,
9
+ * b2x, b2y, b2z, b2time, b2r, b2g, b2b, BstartTime, BendTime
10
+ * ]
11
+ * there is a cutting point between A and B
12
+ *
13
+ */
14
+
15
+ /**
16
+ * ABOVE
17
+ * TO
18
+ * BELOW
19
+
20
+ /**
21
+ * @typedef {Array<number>} vec3 [x, y, z]
22
+ * @typedef {Array<number>} vec2 [x, y]
23
+ * @typedef {Array<number>} vec4 [x, y, z, w]
24
+ * @typedef {number} fraction a number between 0 and 1
25
+ * @typedef {Array<number>} wgs84 [long, lat]
26
+ */
27
+
28
+
29
+ /**
30
+ * @typedef Timetrack
31
+ * @property {Array<vec4>}} coordinates [x,y,z, length]
32
+ * @property {Array<Number>} times
33
+ * @param {Array<Timetrack>} timeTracks
34
+ */
35
+
36
+
37
+
38
+ import { pixelXYLenghtToUnitVectorWithHeight } from "../../Math/methods";
39
+
40
+
41
+
42
+ const processACut = (array, offset) => {
43
+ // first 3 values of array
44
+ const v3 = array.slice(offset, offset + 3);
45
+ const v4 = pixelXYLenghtToUnitVectorWithHeight(v3);
46
+ const time = array[offset + 3];
47
+ return [v4, time];
48
+ }
49
+
50
+
51
+ const timeTrackPluginDataToPointHeatInterpolatorAdapter = (timeTrackPluginData) => {
52
+ const timeTracks = []
53
+
54
+ let offset = 0;
55
+
56
+ let timeTrack = {
57
+ coordinates: [],
58
+ times: []
59
+ }
60
+ while (offset < timeTrackPluginData.length) {
61
+ if (!timeTrackPluginData[offset]) {
62
+ timeTracks.push(timeTrack);
63
+ timeTrack = {
64
+ coordinates: [],
65
+ times: []
66
+ }
67
+ offset += 9;
68
+ }
69
+ const point = processACut(timeTrackPluginData, offset);
70
+ offset += 9;
71
+ timeTrack.coordinates.push(point[0]);
72
+ timeTrack.times.push(point[1]);
73
+ }
74
+ return timeTracks;
75
+ }
76
+
77
+
78
+ export { timeTrackPluginDataToPointHeatInterpolatorAdapter };
File without changes
@@ -0,0 +1,162 @@
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
+
5
+ class PointHeatmapPlugin {
6
+
7
+ constructor(id, { opacity = 1.0, pointSize = 5.0, onInterpolationComplete = () => { } } = {}) {
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
+ this._throttleListener = null;
22
+
23
+ this.timeTrackInterpolationWorker = new Worker(
24
+ new URL(
25
+ '../util/interpolation/timetrack/web-worker.js',
26
+ import.meta.url
27
+ ), { type: 'module' }
28
+ );
29
+ this.timeTrackInterpolationWorker.onmessage = (e) => {
30
+ if (e.data.error) {
31
+ throw new Error(e.data.error);
32
+ }
33
+ if (e.data === true) {
34
+ onInterpolationComplete()
35
+ }
36
+ if (e.data instanceof Float32Array) {
37
+ this.flow.setData(e.data);
38
+ this._throttleListener = null;
39
+ onInterpolationComplete();
40
+ }
41
+ }
42
+ }
43
+
44
+ // globe interaction
45
+
46
+ init(globe, gl) {
47
+ this.globe = globe;
48
+ this.gl = gl;
49
+ this.flow = new PointHeatmapFlow(globe);
50
+
51
+ }
52
+
53
+
54
+ setPointSize(pointSize) {
55
+ if (typeof pointSize !== 'number' || pointSize <= 0) {
56
+ throw new Error('Invalid pointSize');
57
+ }
58
+ this._pointSize = pointSize;
59
+ this.globe.DrawRender();
60
+ }
61
+
62
+
63
+ /**
64
+ * @param {Array<string>}
65
+ * @param {string} mode "interpolated" | "discrete"
66
+ */
67
+
68
+ setColorRamp(values, thresholds, mode = "interpolated") {
69
+ const gl = this.gl
70
+ if (this.gl === null) {
71
+ throw new Error('Plugin not initialized');
72
+ };
73
+ console.log(values, thresholds, mode);
74
+ const rampData = getColorRampModed(values, thresholds, mode);
75
+ console.log(rampData);
76
+ const texture = createTexture(gl, gl.LINEAR, rampData, 256, 1);
77
+ console.log(texture);
78
+ if (this._legendTexture) {
79
+ this.gl.deleteTexture(this._legendTexture);
80
+ }
81
+ this._legendTexture = texture;
82
+ this.globe.DrawRender();
83
+ }
84
+
85
+
86
+ setTime(time) {
87
+ // TODO: WORK ON THIS
88
+ this._time = time;
89
+ if (this._throttleListener === null) {
90
+ this._throttleListener = setTimeout(() => {
91
+ this.timeTrackInterpolationWorker.postMessage({ time: this._time });
92
+ }, 0);
93
+ }
94
+ }
95
+
96
+
97
+ setTimetracks(timeTracks) {
98
+ this.timeTrackInterpolationWorker.postMessage({ timeTracks });
99
+ if (this._time !== null) {
100
+ this.setTime(this._time);
101
+ }
102
+ this.globe.DrawRender();
103
+ }
104
+
105
+
106
+ setOpacity(opacity) {
107
+ if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {
108
+ throw new Error('Invalid opacity');
109
+ }
110
+ this._opacity = opacity;
111
+ this.globe.DrawRender();
112
+ }
113
+
114
+
115
+
116
+ setGeometry() {
117
+ const geometry = this.globe.api_GetCurrentGeometry();
118
+ this.timeTrackInterpolationWorker.postMessage({ geometry });
119
+ if (this._time !== null) {
120
+ this.setTime(this._time);
121
+ }
122
+ }
123
+
124
+
125
+ draw3D() {
126
+ if (this.isReady()) {
127
+ this.flow.draw(this._legendTexture, this._pointSize, this._opacity);
128
+ }
129
+ }
130
+
131
+
132
+ resize() {
133
+ this.flow.resize();
134
+ if (this._time !== null) {
135
+ this.setTime(this._time);
136
+ }
137
+ }
138
+
139
+
140
+ isReady() {
141
+ return (this.gl !== null && this._legendTexture !== null);
142
+ }
143
+
144
+ free() {
145
+ if (this._isFreed) return;
146
+ this.gl.deleteTexture(this._legendTexture);
147
+ this.flow.free();
148
+ this.flow = null;
149
+ this.gl = null;
150
+ this._isFreed = true;
151
+ this.timeTrackInterpolator = null;
152
+ this._legendTexture = null;
153
+ this.timeTrackInterpolationWorker.terminate();
154
+ this.timeTrackInterpolationWorker = null;
155
+ }
156
+ }
157
+
158
+
159
+
160
+
161
+
162
+ export { PointHeatmapPlugin };
@@ -0,0 +1,134 @@
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
+
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
+
28
+ }
29
+
30
+
31
+ setPointSize(pointSize) {
32
+ if (typeof pointSize !== 'number' || pointSize <= 0) {
33
+ throw new Error('Invalid pointSize');
34
+ }
35
+ this._pointSize = pointSize;
36
+ this.globe.DrawRender();
37
+ }
38
+
39
+
40
+ /**
41
+ * @param {Array<string>}
42
+ * @param {string} mode "interpolated" | "discrete"
43
+ */
44
+
45
+ setColorRamp(values, thresholds, mode = "interpolated") {
46
+ const gl = this.gl
47
+ if (this.gl === null) {
48
+ throw new Error('Plugin not initialized');
49
+ };
50
+ console.log(values, thresholds, mode);
51
+ const rampData = getColorRampModed(values, thresholds, mode);
52
+ console.log(rampData);
53
+ const texture = createTexture(gl, gl.LINEAR, rampData, 256, 1);
54
+ console.log(texture);
55
+ if (this._legendTexture) {
56
+ this.gl.deleteTexture(this._legendTexture);
57
+ }
58
+ this._legendTexture = texture;
59
+ this.globe.DrawRender();
60
+ }
61
+
62
+
63
+ setTime(time) {
64
+ this._time = time;
65
+ const data = this.timeTrackInterpolator.interpolate(time);
66
+ if (data === null) {
67
+ return;
68
+ }
69
+ this.flow.setData(data);
70
+ }
71
+
72
+
73
+ setTimetracks(timeTracks) {
74
+ this.timeTrackInterpolator.setTimetracks(timeTracks);
75
+ if (this._time !== null) {
76
+ this.setTime(this._time);
77
+ }
78
+ this.globe.DrawRender();
79
+ }
80
+
81
+
82
+ setOpacity(opacity) {
83
+ if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {
84
+ throw new Error('Invalid opacity');
85
+ }
86
+ this._opacity = opacity;
87
+ this.globe.DrawRender();
88
+ }
89
+
90
+
91
+
92
+ setGeometry() {
93
+ const geometry = this.globe.api_GetCurrentGeometry();
94
+ this.timeTrackInterpolator.setGeometry(geometry);
95
+ if (this._time !== null) {
96
+ this.setTime(this._time);
97
+ }
98
+ }
99
+
100
+
101
+ draw3D() {
102
+ if (this.isReady()) {
103
+ this.flow.draw(this._legendTexture, this._pointSize, this._opacity);
104
+ }
105
+ }
106
+
107
+
108
+ resize() {
109
+ this.timeTrackInterpolator.setGeometry(this.globe.api_GetCurrentGeometry());
110
+ this.flow.resize();
111
+ if (this._time !== null) {
112
+ this.setTime(this._time);
113
+ }
114
+ }
115
+
116
+
117
+ isReady() {
118
+ return (this.gl !== null && this._legendTexture !== null);
119
+ }
120
+
121
+ free() {
122
+ if (this._isFreed) return;
123
+ this.gl.deleteTexture(this._legendTexture);
124
+ this.flow.free();
125
+ this.flow = null;
126
+ this.gl = null;
127
+ this._isFreed = true;
128
+ this.timeTrackInterpolator = null;
129
+ this._legendTexture = null;
130
+ }
131
+ }
132
+
133
+
134
+ export { PointHeatmapPlugin };