@pirireis/webglobeplugins 0.7.0 → 0.7.2

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
@@ -1,7 +1,6 @@
1
1
 
2
- const WORLD_RADIUS_3D = 6371.137;
3
- const WORLD_RADIUS_MERCATOR = 6371137;
4
- const POLE = 20037508.34;
2
+ const WORLD_RADIUS_3D = 6378.137;
3
+ const WORLD_RADIUS_MERCATOR = 6378136.99911;
5
4
 
6
5
  /**
7
6
  * @typedef {Array<number>} vec3 [x, y, z]
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
- export { wind, waveparticles, timetracks, rangerings, compassrose, heatwave, util, programs, arrowfield, partialring };
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pirireis/webglobeplugins",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "main": "index.js",
5
5
  "author": "Toprak Nihat Deniz Ozturk",
6
6
  "license": "MIT"
@@ -0,0 +1,3 @@
1
+ import { PointHeatmapPlugin } from "./plugin-webworker";
2
+ import { timeTrackPluginDataToPointHeatInterpolatorAdapter } from "./adaptors/timetracksplugin-format-to-this";
3
+ // export { PointHeatmapPlugin, timeTrackPluginDataToPointHeatInterpolatorAdapter };
@@ -1,5 +1,5 @@
1
1
  import { PointHeatmapFlow } from "./point-to-heat-map-flow";
2
- import { TimeTrackInterpolator } from "../util/interpolation/timetrack/timetrack-interpolator";
2
+ import { webworkerStr } from "../util/interpolation/timetrack/web-worker-str";
3
3
  import { createTexture, getColorRampModed } from "../util";
4
4
 
5
5
  class PointHeatmapPlugin {
@@ -11,27 +11,19 @@ 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
-
23
- this.timeTrackInterpolationWorker = new Worker(
24
- new URL(
25
- '../util/interpolation/timetrack/web-worker.js',
26
- import.meta.url
27
- ), { type: 'module' }
28
- );
19
+ const blob = new Blob([webworkerStr], { type: 'application/javascript' });
20
+ this.timeTrackInterpolationWorker = new Worker(URL.createObjectURL(blob), { type: 'module' });
29
21
  this.timeTrackInterpolationWorker.onmessage = (e) => {
30
22
  if (e.data.error) {
31
23
  throw new Error(e.data.error);
32
24
  }
33
25
  if (e.data === true) {
34
- onInterpolationComplete()
26
+ onInterpolationComplete();
35
27
  }
36
28
  if (e.data instanceof Float32Array) {
37
29
  this.flow.setData(e.data);
@@ -0,0 +1,9 @@
1
+ const createWorker = () => new Worker(
2
+ new URL(
3
+ './web-worker.js',
4
+ import.meta.url
5
+ ), { type: 'module' }
6
+ );
7
+
8
+
9
+ export {createWorker}
@@ -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 };