@pirireis/webglobeplugins 0.7.0 → 0.7.1
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.
package/Math/methods.js
CHANGED
package/index.js
CHANGED
|
@@ -8,4 +8,5 @@ import * as compassrose from "./compassrose";
|
|
|
8
8
|
import * as heatwave from "./heatwave";
|
|
9
9
|
import * as util from "./util";
|
|
10
10
|
import * as programs from "./programs";
|
|
11
|
-
|
|
11
|
+
import * as pointheatmap from "./point-heat-map";
|
|
12
|
+
export { wind, waveparticles, timetracks, rangerings, compassrose, heatwave, util, programs, arrowfield, partialring, pointheatmap };
|
package/package.json
CHANGED
package/point-heat-map/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PointHeatmapFlow } from "./point-to-heat-map-flow";
|
|
2
|
-
import {
|
|
2
|
+
import { webworkerStr } from "../util/interpolation/timetrack/web-worker-str";
|
|
3
3
|
import { createTexture, getColorRampModed } from "../util";
|
|
4
4
|
|
|
5
5
|
class PointHeatmapPlugin {
|
|
@@ -11,21 +11,25 @@ class PointHeatmapPlugin {
|
|
|
11
11
|
this.densityToLegendProgram = null;
|
|
12
12
|
this._time = null;
|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
this._opacity = opacity;
|
|
16
15
|
this._pointSize = pointSize;
|
|
17
16
|
this._legendTexture = null;
|
|
18
|
-
// this.timeTrackInterpolator = new TimeTrackInterpolator();
|
|
19
|
-
|
|
20
17
|
|
|
21
18
|
this._throttleListener = null;
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
try {
|
|
21
|
+
|
|
22
|
+
this.timeTrackInterpolationWorker = new Worker(
|
|
23
|
+
new URL(
|
|
24
|
+
'../util/interpolation/timetrack/web-worker.js',
|
|
25
|
+
import.meta.url
|
|
26
|
+
), { type: 'module' }
|
|
27
|
+
);
|
|
28
|
+
} catch (e) {
|
|
29
|
+
console.log(e);
|
|
30
|
+
const blob = new Blob([webworkerStr], { type: 'application/javascript' });
|
|
31
|
+
this.timeTrackInterpolationWorker = new Worker(URL.createObjectURL(blob), { type: 'module' });
|
|
32
|
+
}
|
|
29
33
|
this.timeTrackInterpolationWorker.onmessage = (e) => {
|
|
30
34
|
if (e.data.error) {
|
|
31
35
|
throw new Error(e.data.error);
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
const webworkerStr = `
|
|
2
|
+
|
|
3
|
+
const WORLD_RADIUS_3D = 6378.137;
|
|
4
|
+
const WORLD_RADIUS_MERCATOR = 6378136.99911;
|
|
5
|
+
|
|
6
|
+
const dot3 = (a, b) => {
|
|
7
|
+
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const sphericalLinearInterpolation_UnitVector = (normalizedA, normalizedB, ratio) => {
|
|
11
|
+
const theta = Math.acos(dot3(normalizedA, normalizedB));
|
|
12
|
+
if (theta < 0.000001) return normalizedA; // CALIBRATE?
|
|
13
|
+
const sinTheta = Math.sin(theta);
|
|
14
|
+
const result = [
|
|
15
|
+
(Math.sin((1.0 - ratio) * theta) * normalizedA[0] + Math.sin(ratio * theta) * normalizedB[0]) / sinTheta,
|
|
16
|
+
(Math.sin((1.0 - ratio) * theta) * normalizedA[1] + Math.sin(ratio * theta) * normalizedB[1]) / sinTheta,
|
|
17
|
+
(Math.sin((1.0 - ratio) * theta) * normalizedA[2] + Math.sin(ratio * theta) * normalizedB[2]) / sinTheta
|
|
18
|
+
];
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const radianToMercator = (xy) => {
|
|
23
|
+
return [WORLD_RADIUS_MERCATOR * xy[0], WORLD_RADIUS_MERCATOR * Math.log(Math.tan(Math.PI / 4 + xy[1] / 2))];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
const cartesian3dToRadian = (cartesian) => {
|
|
28
|
+
const x = cartesian[0];
|
|
29
|
+
const y = cartesian[1];
|
|
30
|
+
const z = cartesian[2];
|
|
31
|
+
// const length = Math.sqrt(x * x + y * y + z * z);
|
|
32
|
+
const long = Math.atan2(y, x);
|
|
33
|
+
const lat = Math.asin(z)// length);
|
|
34
|
+
return [long, lat];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const sphericalLinearInterpolation_Mercator = (normalizedA, normalizedB, ratio) => {
|
|
39
|
+
const unitVector = sphericalLinearInterpolation_UnitVector(normalizedA, normalizedB, ratio);
|
|
40
|
+
const angles = cartesian3dToRadian(unitVector);
|
|
41
|
+
return radianToMercator(angles);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const sphericalLinearInterpolation_Cartesian3d = (a, b, ratio) => {
|
|
45
|
+
const unitVector = sphericalLinearInterpolation_UnitVector(a, b, ratio);
|
|
46
|
+
const height = a[3] + (b[3] - a[3]) * ratio;
|
|
47
|
+
return [unitVector[0] * height, unitVector[1] * height, unitVector[2] * height];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const findFirstIndexInRange = (container, value) => {
|
|
51
|
+
let start = 0;
|
|
52
|
+
let end = container.length - 1;
|
|
53
|
+
let mid = 0;
|
|
54
|
+
while (start <= end) {
|
|
55
|
+
mid = Math.floor((start + end) / 2);
|
|
56
|
+
if (container[mid] <= value && value <= container[mid + 1]) return mid;
|
|
57
|
+
if (container[mid] < value) start = mid + 1;
|
|
58
|
+
else end = mid - 1;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const GEOMETRY = Object.freeze({
|
|
64
|
+
CARTESIAN3D: 0,
|
|
65
|
+
MERCATOR: 1,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
class TimeTrackInterpolator {
|
|
69
|
+
/**
|
|
70
|
+
* @typedef Timetrack
|
|
71
|
+
* @property {Array<vec4>}} coordinates [x,y,z, length]
|
|
72
|
+
* @property {Array<Number>} times
|
|
73
|
+
* @param {Array<Timetrack>} timeTracks
|
|
74
|
+
*/
|
|
75
|
+
constructor({ timeTracks, bbox = null, geometry = GEOMETRY.CARTESIAN3D } = {}) {
|
|
76
|
+
this.timeTracks = null;
|
|
77
|
+
this.timeTracksStartTimes = null;
|
|
78
|
+
this.geometry = geometry;
|
|
79
|
+
if (timeTracks) this.setTimetracks(timeTracks);
|
|
80
|
+
if (bbox) this.setBbox(bbox);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
setGeometry(geometry) {
|
|
85
|
+
if (geometry !== GEOMETRY.CARTESIAN3D && geometry !== GEOMETRY.MERCATOR) {
|
|
86
|
+
throw new Error('Invalid geometry');
|
|
87
|
+
}
|
|
88
|
+
this.geometry = geometry;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setTimetracks(timeTracks) {
|
|
92
|
+
console.log("timetracks:", timeTracks);
|
|
93
|
+
this.timeTracks = timeTracks;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
interpolate(time) {
|
|
98
|
+
const { timeTracks, geometry } = this;
|
|
99
|
+
if (!timeTracks) { return null; }
|
|
100
|
+
const resultArray = [];
|
|
101
|
+
const info = {
|
|
102
|
+
outOfRange: 0,
|
|
103
|
+
processed: 0,
|
|
104
|
+
}
|
|
105
|
+
for (let i = 0; i < timeTracks.length; i++) {
|
|
106
|
+
const { times, coordinates } = timeTracks[i];
|
|
107
|
+
|
|
108
|
+
if (times[times.length - 1] < time) continue;
|
|
109
|
+
info.processed++;
|
|
110
|
+
const timeIndex = findFirstIndexInRange(times, time);
|
|
111
|
+
if (timeIndex === null) { info.outOfRange++; continue; }
|
|
112
|
+
const timeFraction = (time - times[timeIndex]) / (times[timeIndex + 1] - times[timeIndex]);
|
|
113
|
+
const interpolated = (geometry === GEOMETRY.CARTESIAN3D) ?
|
|
114
|
+
sphericalLinearInterpolation_Cartesian3d(coordinates[timeIndex], coordinates[timeIndex + 1], timeFraction) :
|
|
115
|
+
sphericalLinearInterpolation_Mercator(coordinates[timeIndex], coordinates[timeIndex + 1], timeFraction);
|
|
116
|
+
resultArray.push(...interpolated);
|
|
117
|
+
}
|
|
118
|
+
return new Float32Array(resultArray);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
// implicit methods
|
|
123
|
+
|
|
124
|
+
_orderTimeTracks() {
|
|
125
|
+
this.timeTracks.sort((a, b) => a.times[0] - b.times[0]);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
_setStartTimes() {
|
|
129
|
+
this.timeTracksStartTimes = this.timeTracks.map(tt => tt.times[0]);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const interpolator = new TimeTrackInterpolator({ geometry: GEOMETRY.CARTESIAN3D });
|
|
134
|
+
|
|
135
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
136
|
+
self.onmessage = function (e) {
|
|
137
|
+
|
|
138
|
+
const { geometry = null, timeTracks = null, time = null } = e.data;
|
|
139
|
+
|
|
140
|
+
if (geometry !== null) {
|
|
141
|
+
try {
|
|
142
|
+
interpolator.setGeometry(geometry);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
145
|
+
self.postMessage({ error: error.message });
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (timeTracks !== null) {
|
|
151
|
+
try {
|
|
152
|
+
interpolator.setTimetracks(timeTracks);
|
|
153
|
+
} catch (error) {
|
|
154
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
155
|
+
self.postMessage({ error: error.message });
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (time !== null) {
|
|
161
|
+
try {
|
|
162
|
+
const result = interpolator.interpolate(time);
|
|
163
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
164
|
+
self.postMessage(result, [result.buffer]);
|
|
165
|
+
return;
|
|
166
|
+
} catch (error) {
|
|
167
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
168
|
+
self.postMessage({ error: error.message });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/* eslint-disable-next-line no-restricted-globals */
|
|
173
|
+
self.postMessage(true);
|
|
174
|
+
}
|
|
175
|
+
`;
|
|
176
|
+
export { webworkerStr };
|