@pirireis/webglobeplugins 0.6.18 → 0.6.19
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/bearing-line/plugin-flat-old.js +500 -0
- package/bearing-line/plugin.js +97 -25
- package/circle-line-chain/plugin.js +60 -8
- package/circle-line-chain/plugin_newer_old.js +406 -0
- package/package.json +1 -1
- package/programs/line-on-globe/circle-accurate-3d.js +185 -0
- package/programs/line-on-globe/circle-accurate-flat.js +200 -0
- package/programs/line-on-globe/circle-accurate.js +2 -0
- package/programs/rings/partial-ring/piece-of-pie.js +3 -3
- package/util/jshelpers/data-filler.js +19 -0
- package/util/shaderfunctions/geometrytransformations.js +8 -3
- package/write-text/context-text3.js +4 -0
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
import { pieceOfPieProgramCache } from '../programs/rings/partial-ring/piece-of-pie';
|
|
2
|
+
import { LineOnGlobeCache } from '../programs/line-on-globe/naive-accurate';
|
|
3
|
+
import { CircleCache, mercator_calculation_mode } from '../programs/line-on-globe/circle-accurate-cpu';
|
|
4
|
+
import { BufferOrchestrator, BufferManager } from '../util/account';
|
|
5
|
+
import { AngledLineProgramCache } from '../programs/line-on-globe/angled-line'; // TODO calculate the bearing target for 2d and 3d and use lineOnGlobeProgram
|
|
6
|
+
import { mapGetOrThrow } from "../util/check/get";
|
|
7
|
+
import { ContextTextWriter } from '../write-text/context-text'
|
|
8
|
+
export const RINGPARTIAL_DRAW_MODE = Object.freeze({
|
|
9
|
+
LINE_STRIP: "LINE_STRIP",
|
|
10
|
+
TRIANGLE_FAN: "TRIANGLE_FAN",
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const constraintFloat = (x, lowerBound, upperBound) => {
|
|
14
|
+
if (typeof x !== "number") throw new Error("type must be numberic")
|
|
15
|
+
if (lowerBound > x || x > upperBound) throw new Error(`input must be between ${lowerBound} - ${upperBound}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* partial ring angle should be different on globe and mercator.
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object}textContextInjection
|
|
26
|
+
* @property {string} id
|
|
27
|
+
* @property {function} coordsAdaptor
|
|
28
|
+
* @property {function} textAdaptor
|
|
29
|
+
* @property {ContextTextWriter} writer
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
export default class Plugin {
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @param {*} id
|
|
37
|
+
* @param {Map<[K ,{writer:ContextTextWriter, coordsAdaptor, textAdaptor}]} textContextInjectionMap import { ContextTextWriter } from '@pirireis/webglobeplugins/write-text/context-text';
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
constructor(id, { opacity = 1, textContextInjectionMap = new Map(), drawVRM = true, drawBearingLine = true, drawAngleRing = true, drawText = true } = {}) {
|
|
42
|
+
this.id = id;
|
|
43
|
+
this._opacity = opacity;
|
|
44
|
+
this.bufferOrchestrator = new BufferOrchestrator({ capacity: 10 });
|
|
45
|
+
this._checkTextContextInjectionMap(textContextInjectionMap);
|
|
46
|
+
this._textContextInjectionMap = textContextInjectionMap;
|
|
47
|
+
this.drawVRM = drawVRM;
|
|
48
|
+
this.drawBearingLine = drawBearingLine;
|
|
49
|
+
this.drawAngleRing = drawAngleRing;
|
|
50
|
+
this.drawText = drawText;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setDoDrawVRM(bool) {
|
|
54
|
+
if (bool === this.drawVRM) return;
|
|
55
|
+
this.drawVRM = bool;
|
|
56
|
+
this.globe.DrawRender();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setDoDrawText(bool) {
|
|
60
|
+
if (bool === this.drawText) return;
|
|
61
|
+
this.drawText = bool;
|
|
62
|
+
this.globe.DrawRender();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setDoDrawText(bool) {
|
|
66
|
+
if (bool === this.drawText) return;
|
|
67
|
+
this.drawText = bool;
|
|
68
|
+
this.globe.DrawRender();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_checkTextContextInjectionMap(textContextInjectionMap) {
|
|
72
|
+
if (!(textContextInjectionMap instanceof Map)) throw new TypeError("textContextInjectionMap is not instance of Map");
|
|
73
|
+
textContextInjectionMap.forEach((v) => {
|
|
74
|
+
if (typeof v !== 'object') throw new TypeError("textContextInjectionMap format is wrong");
|
|
75
|
+
if (typeof v.coordsAdaptor !== 'function') throw new TypeError("textContextInjectionMap coordsAdaptor format is wrong");
|
|
76
|
+
if (typeof v.textAdaptor !== 'function') throw new TypeError("textContextInjectionMap textAdaptor format is wrong");
|
|
77
|
+
if (!(v.writer instanceof ContextTextWriter)) throw new TypeError("textContextInjectionMap writer is not instance of ContextTextWriter");
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
setDoDrawAngleRing(bool) {
|
|
82
|
+
if (bool === this.drawAngleRing) return;
|
|
83
|
+
this.drawAngleRing = bool;
|
|
84
|
+
this.globe.DrawRender();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
settextContextInjectionMap(textContextInjectionMap, data = null) {
|
|
89
|
+
this._textContextInjectionMap = textContextInjectionMap;
|
|
90
|
+
this._textContextInjectionMap.forEach(({ writer }) => writer.clear());
|
|
91
|
+
if (data) {
|
|
92
|
+
for (const item of data) {
|
|
93
|
+
this._insertTexts(item);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
setOpacity(opacity) {
|
|
100
|
+
constraintFloat(opacity, 0, 1);
|
|
101
|
+
this._opacity = opacity;
|
|
102
|
+
this._textContextInjectionMap.forEach(({ writer }) => writer.setOpacity(opacity));
|
|
103
|
+
this.globe.DrawRender();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
init(globe, gl) {
|
|
110
|
+
this.gl = gl;
|
|
111
|
+
this.globe = globe;
|
|
112
|
+
this.lineProgram = LineOnGlobeCache.get(globe);
|
|
113
|
+
this.ringProgram = pieceOfPieProgramCache.get(globe);
|
|
114
|
+
this.angledLineProgram = AngledLineProgramCache.get(globe);
|
|
115
|
+
this.circleProgram = CircleCache.get(globe);
|
|
116
|
+
// this.angleTextContext = new ContextTextWriter(globe);
|
|
117
|
+
// this.distanceTextContext = new ContextTextWriter(globe);
|
|
118
|
+
{
|
|
119
|
+
// createBuffers
|
|
120
|
+
const bufferType = "DYNAMIC_DRAW";
|
|
121
|
+
const initialCapacity = this.bufferOrchestrator.capacity;
|
|
122
|
+
this.bufferManagersCompMap = new Map(
|
|
123
|
+
[
|
|
124
|
+
|
|
125
|
+
["centerCoords2d", {
|
|
126
|
+
'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
|
|
127
|
+
'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.long, item.lat)),
|
|
128
|
+
}],
|
|
129
|
+
["centerCoords2dflat", {
|
|
130
|
+
'bufferManager': new BufferManager(gl, 722, { bufferType, initialCapacity }),
|
|
131
|
+
'adaptor': (item) => item.centerCoords2dflat,
|
|
132
|
+
}],
|
|
133
|
+
["centerCoords3d", {
|
|
134
|
+
'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
|
|
135
|
+
'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.long, item.lat, 0, 0)),
|
|
136
|
+
}],
|
|
137
|
+
["targetCoords2d", {
|
|
138
|
+
'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
|
|
139
|
+
'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.endLong, item.endLat))
|
|
140
|
+
}],
|
|
141
|
+
["targetCoords3d", {
|
|
142
|
+
'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
|
|
143
|
+
'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.endLong, item.endLat, 0, 0))
|
|
144
|
+
}],
|
|
145
|
+
["bearingTargetCoords2d", {
|
|
146
|
+
'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
|
|
147
|
+
'adaptor': (item) => new Float32Array(globe.api_GetMercator2DPoint(item.bearingLong, item.bearingLat))
|
|
148
|
+
}],
|
|
149
|
+
["bearingTargetCoords3d", {
|
|
150
|
+
'bufferManager': new BufferManager(gl, 3, { bufferType, initialCapacity }),
|
|
151
|
+
'adaptor': (item) => new Float32Array(globe.api_GetCartesian3DPoint(item.bearingLong, item.bearingLat, 0, 0))
|
|
152
|
+
}],
|
|
153
|
+
["startAngle", {
|
|
154
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
155
|
+
'adaptor': (item) => new Float32Array([item.startAngle])
|
|
156
|
+
}],
|
|
157
|
+
["tailAngle", {
|
|
158
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
159
|
+
'adaptor': (item) => new Float32Array([item.tailAngle])
|
|
160
|
+
}],
|
|
161
|
+
["startAngle2d", {
|
|
162
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
163
|
+
'adaptor': (item) => new Float32Array([item.startAngle2d])
|
|
164
|
+
}],
|
|
165
|
+
["tailAngle2d", {
|
|
166
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
167
|
+
'adaptor': (item) => new Float32Array([item.tailAngle2d])
|
|
168
|
+
}],
|
|
169
|
+
["startAngle3d", {
|
|
170
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
171
|
+
'adaptor': (item) => new Float32Array([item.startAngle3d])
|
|
172
|
+
}],
|
|
173
|
+
["tailAngle3d", {
|
|
174
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
175
|
+
'adaptor': (item) => new Float32Array([item.tailAngle3d])
|
|
176
|
+
}],
|
|
177
|
+
["bearingDashRatio", {
|
|
178
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
179
|
+
'adaptor': (item) => new Float32Array([0])
|
|
180
|
+
}],
|
|
181
|
+
["rgba", {
|
|
182
|
+
'bufferManager': new BufferManager(gl, 4, { bufferType, initialCapacity }),
|
|
183
|
+
'adaptor': (item) => new Float32Array(item.rgba)
|
|
184
|
+
}],
|
|
185
|
+
["radius", {
|
|
186
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
187
|
+
'adaptor': (item) => new Float32Array([item.radius])
|
|
188
|
+
}],
|
|
189
|
+
["rgbaMode", {
|
|
190
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
191
|
+
'adaptor': (item) => new Float32Array([item.rgbaMode])
|
|
192
|
+
}],
|
|
193
|
+
["dashRatio", {
|
|
194
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
195
|
+
'adaptor': (item) => new Float32Array([item.dashRatio])
|
|
196
|
+
}],
|
|
197
|
+
["bearingAngle", {
|
|
198
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
199
|
+
'adaptor': (item) => new Float32Array([item.bearingAngle])
|
|
200
|
+
}],
|
|
201
|
+
["bigRadius", {
|
|
202
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
203
|
+
'adaptor': (item) => new Float32Array([item.bigRadius])
|
|
204
|
+
}],
|
|
205
|
+
["dashOpacity", {
|
|
206
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
207
|
+
'adaptor': (item) => new Float32Array([item.dashOpacity])
|
|
208
|
+
}],
|
|
209
|
+
["circleDashAngle", {
|
|
210
|
+
'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
|
|
211
|
+
'adaptor': (item) => new Float32Array([item.circleDashAngle / 360])
|
|
212
|
+
}]
|
|
213
|
+
]
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
const obj = function (bufferManagerComp, divisor = 1) {
|
|
219
|
+
return { 'buffer': bufferManagerComp.bufferManager.buffer, 'stride': 0, 'offset': 0, divisor }
|
|
220
|
+
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
this.lineVao = this.lineProgram.createVAO(
|
|
224
|
+
...['centerCoords2d', 'centerCoords3d', 'targetCoords2d', 'targetCoords3d', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
|
|
225
|
+
this.ringVao = this.ringProgram.createVAO(
|
|
226
|
+
...['centerCoords2d', 'centerCoords3d',
|
|
227
|
+
'startAngle2d',
|
|
228
|
+
'tailAngle2d',
|
|
229
|
+
'startAngle3d',
|
|
230
|
+
'tailAngle3d',
|
|
231
|
+
'rgba',
|
|
232
|
+
'radius',
|
|
233
|
+
'rgbaMode'].map(key => obj(this.bufferManagersCompMap.get(key))));
|
|
234
|
+
{
|
|
235
|
+
this.bearingLineVAO = this.lineProgram.createVAO(
|
|
236
|
+
...['centerCoords2d', 'centerCoords3d', 'bearingTargetCoords2d', 'bearingTargetCoords3d', 'bearingDashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
|
|
237
|
+
}
|
|
238
|
+
// centerObj, startAngleObj, radiusObj, colorObj, dashRatioObj, dashOpacityObj
|
|
239
|
+
this.circleVao = this.circleProgram.createVAO(
|
|
240
|
+
{
|
|
241
|
+
divisor: 0,
|
|
242
|
+
stride: 0,
|
|
243
|
+
offset: 0,
|
|
244
|
+
buffer: this.bufferManagersCompMap.get("centerCoords2dflat").bufferManager.buffer
|
|
245
|
+
},
|
|
246
|
+
...["centerCoords3d", "bigRadius", "rgba", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key, 361)))
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
draw3D() {
|
|
254
|
+
const { gl } = this;
|
|
255
|
+
gl.disable(gl.DEPTH_TEST);
|
|
256
|
+
|
|
257
|
+
this.lineProgram.draw(this.lineVao, this.bufferOrchestrator.length, this._opacity);
|
|
258
|
+
if (this.drawAngleRing) {
|
|
259
|
+
this.ringProgram.draw(this.bufferOrchestrator.length, this.ringVao, 360, this._opacity * 0.8, RINGPARTIAL_DRAW_MODE.TRIANGLE_FAN);
|
|
260
|
+
this.ringProgram.draw(this.bufferOrchestrator.length, this.ringVao, 360, this._opacity, RINGPARTIAL_DRAW_MODE.LINE_STRIP);
|
|
261
|
+
}
|
|
262
|
+
if (this.drawBearingLine) {
|
|
263
|
+
this.lineProgram.draw(this.bearingLineVAO, this.bufferOrchestrator.length, this._opacity * 0.8);
|
|
264
|
+
}
|
|
265
|
+
if (this.drawVRM) {
|
|
266
|
+
this.circleProgram.draw(this.circleVao, this.bufferOrchestrator.length, this._opacity, mercator_calculation_mode.CPU);
|
|
267
|
+
}
|
|
268
|
+
if (this.drawText) {
|
|
269
|
+
this._textContextInjectionMap.forEach((e) => { e.writer.draw(); });
|
|
270
|
+
}
|
|
271
|
+
gl.enable(gl.DEPTH_TEST);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* @typedef {{key, long, lat, endLong, endLat, bearingAngle, radius, rgba:[4numbers], rgbaMode, bigRadius, dashRatio, dashOpacity, circleDashAngle}} item
|
|
277
|
+
* @property {string} key
|
|
278
|
+
* @property {number} long
|
|
279
|
+
* @property {number} lat
|
|
280
|
+
* @property {number} endLong
|
|
281
|
+
* @property {number} endLat
|
|
282
|
+
* @property {number} bearingAngle 0-360
|
|
283
|
+
* @property {number} radius angle ring radius
|
|
284
|
+
* @property {Array<4numbers>} rgba [r,g,b,a]
|
|
285
|
+
* @property {number} rgbaMode 0 constant, 1 fading, 2 hides angle ring
|
|
286
|
+
* @property {number} bigRadius undefined means it will be calculated from long, lat, endLong, endLat
|
|
287
|
+
* @property {number} dashRatio 0-1
|
|
288
|
+
* @property {number} dashOpacity 0-1
|
|
289
|
+
* @property {number} circleDashAngle 0-360
|
|
290
|
+
* @param {Array<item>} items
|
|
291
|
+
* @param {Array<string>} textWriterInjectionSubSetIDs | textContextInjectionMap keys to be used for writing text.
|
|
292
|
+
*/
|
|
293
|
+
insertBulk(items, textWriterInjectionSubSetIDs = []) {
|
|
294
|
+
const { globe, bufferOrchestrator, bufferManagersCompMap } = this;// angleTextContext, distanceTextContext,
|
|
295
|
+
const textWriterInjectionSubSets = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);
|
|
296
|
+
const data = []
|
|
297
|
+
for (let item of items) {
|
|
298
|
+
this._insertTexts(item, textWriterInjectionSubSets);
|
|
299
|
+
data.push(this.__insertAdaptor(item));
|
|
300
|
+
}
|
|
301
|
+
bufferOrchestrator.insertBulk(data, bufferManagersCompMap);
|
|
302
|
+
this._textContextInjectionMap.forEach((v) => {
|
|
303
|
+
const { writer } = v;
|
|
304
|
+
writer.updateOpacityBulk(items, (e) => e.key, (e) => e.rgba[3]);
|
|
305
|
+
})
|
|
306
|
+
globe.DrawRender();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
deleteBulk(keys) {
|
|
313
|
+
this.bufferOrchestrator.deleteBulk(keys, this.bufferManagersCompMap);
|
|
314
|
+
this._deleteTexts(keys);
|
|
315
|
+
this.globe.DrawRender();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
defrag() {
|
|
320
|
+
this.bufferOrchestrator.defrag(this.bufferManagersCompMap);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
*
|
|
325
|
+
* @param {Array<{key, long, lat, endLong, endLat, bearingAngle}>} items
|
|
326
|
+
* @param {Array<string>} textWriterInjectionSubSetIDs | textContextInjectionMap keys to be used for writing text.
|
|
327
|
+
*/
|
|
328
|
+
updateCoordinatesBulk(items, textWriterInjectionSubSetIDs = []) { //TODO
|
|
329
|
+
const injectionsSubSet = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);;
|
|
330
|
+
const { globe, bufferOrchestrator, bufferManagersCompMap, } = this;
|
|
331
|
+
const data = []
|
|
332
|
+
for (let item of items) {
|
|
333
|
+
this._insertTexts(item, injectionsSubSet);
|
|
334
|
+
data.push(this.__updateCoordsAdaptor(item));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
bufferOrchestrator.updateBulk(data, bufferManagersCompMap, ["centerCoords2d", "centerCoords3d", "targetCoords2d", "targetCoords3d", "startAngle", "tailAngle",
|
|
338
|
+
"startAngle2d", "tailAngle2d", "startAngle3d", "tailAngle3d", "bearingTargetCoords2d", "bearingTargetCoords3d", "centerCoords2dflat",
|
|
339
|
+
"bearingAngle", "bigRadius", "radius"]);
|
|
340
|
+
globe.DrawRender();
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
*
|
|
346
|
+
* @param {*} items some colums EXCEPT positional ones
|
|
347
|
+
* @param {string} propertyIDs
|
|
348
|
+
* @param {string} textWriterInjectionSubSetIDs
|
|
349
|
+
* Do NOT send empty data if property ID of this data is entered or NaN is loaded to the buffer, resulting in an unwanted behaviour.
|
|
350
|
+
*/
|
|
351
|
+
updatePartial(items, propertyIDs = [], textWriterInjectionSubSetIDs = []) { // textWriterInjectionSubSetIDs = []
|
|
352
|
+
if (propertyIDs.length === 0) console.warn("updatePartial is called with no target propertyIDs");
|
|
353
|
+
const { _textContextInjectionMap, bufferOrchestrator, bufferManagersCompMap } = this;
|
|
354
|
+
const writers = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);
|
|
355
|
+
for (let item of items) { this._insertTexts(item, writers) }
|
|
356
|
+
bufferOrchestrator.updateBulk(items, bufferManagersCompMap, propertyIDs);
|
|
357
|
+
// patch to update text opacity
|
|
358
|
+
for (const property of propertyIDs) {
|
|
359
|
+
if (property === "rgba") {
|
|
360
|
+
_textContextInjectionMap.forEach((v) => {
|
|
361
|
+
const { writer } = v;
|
|
362
|
+
writer.updateOpacityBulk(items, (e) => e.key, (e) => e.rgba[3]);
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
this.globe.DrawRender();
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
__insertAdaptor(item) {
|
|
371
|
+
|
|
372
|
+
const rgba = item.rgba !== undefined ? item.rgba : [0, 0, 0, 0];
|
|
373
|
+
const rgbaMode = item.rgbaMode !== undefined ? item.rgbaMode : 0;
|
|
374
|
+
const dashRatio = item.dashRatio !== undefined ? item.dashRatio : 1.0;
|
|
375
|
+
const dashOpacity = item.dashOpacity !== undefined ? item.dashOpacity : 0.9;
|
|
376
|
+
const circleDashAngle = item.circleDashAngle !== undefined ? item.circleDashAngle : 360;
|
|
377
|
+
|
|
378
|
+
const coordsData = this.__updateCoordsAdaptor(item);
|
|
379
|
+
|
|
380
|
+
return {
|
|
381
|
+
...coordsData,
|
|
382
|
+
rgba,
|
|
383
|
+
dashRatio,
|
|
384
|
+
dashOpacity,
|
|
385
|
+
circleDashAngle,
|
|
386
|
+
rgbaMode
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
__updateCoordsAdaptor(item) {
|
|
392
|
+
const { globe } = this;
|
|
393
|
+
const lat = radian(item.lat)
|
|
394
|
+
const long = radian(item.long)
|
|
395
|
+
const endLat = radian(item.endLat)
|
|
396
|
+
const endLong = radian(item.endLong)
|
|
397
|
+
const bigRadius = item.bigRadius !== undefined ? item.bigRadius : globe.Math.GetDist3D(item.long, item.lat, item.endLong, item.endLat);
|
|
398
|
+
const radius = item.radius !== undefined ? item.radius : bigRadius * 0.2;
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
const { long: bearingLong, lat: bearingLat } = globe.Math.FindPointByPolar(item.long, item.lat, bigRadius, item.bearingAngle)
|
|
402
|
+
|
|
403
|
+
const startAngle2d = calculateStartAngle(long, lat, endLong, endLat);
|
|
404
|
+
const bearingAngle2d = calculateStartAngle(long, lat, radian(bearingLong), radian(bearingLat))
|
|
405
|
+
let tailAngle2d = bearingAngle2d - startAngle2d;
|
|
406
|
+
if (tailAngle2d > 0) {
|
|
407
|
+
tailAngle2d -= Math.PI * 2;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const bearingAngle = radian(item.bearingAngle - 90);
|
|
411
|
+
const startAngle3d = radian(globe.Math.GetAzimuthAngle(item.long, item.lat, item.endLong, item.endLat)) - radian(90);
|
|
412
|
+
let tailAngle3d = bearingAngle - startAngle3d;
|
|
413
|
+
if (tailAngle3d > 0) {
|
|
414
|
+
tailAngle3d -= Math.PI * 2;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const centerCoords2dflat = new Float32Array(722);
|
|
418
|
+
const startAngleOfCircle = startAngle2d * 180 / Math.PI;
|
|
419
|
+
for (let i = 0; i < 360; i++) {
|
|
420
|
+
const { long: lg, lat: lt } = globe.Math.FindPointByPolar(item.long, item.lat, bigRadius, i);
|
|
421
|
+
centerCoords2dflat.set(globe.api_GetMercator2DPoint(lg, lt), i * 2);
|
|
422
|
+
}
|
|
423
|
+
centerCoords2dflat.set([centerCoords2dflat[0], centerCoords2dflat[1]], 720);
|
|
424
|
+
|
|
425
|
+
// console.log(centerCoords2dflat);
|
|
426
|
+
return {
|
|
427
|
+
key: item.key,
|
|
428
|
+
lat: item.lat,
|
|
429
|
+
long: item.long,
|
|
430
|
+
endLat: item.endLat,
|
|
431
|
+
endLong: item.endLong,
|
|
432
|
+
bearingAngle,
|
|
433
|
+
radius,
|
|
434
|
+
bigRadius,
|
|
435
|
+
startAngle2d,
|
|
436
|
+
tailAngle2d,
|
|
437
|
+
startAngle3d,
|
|
438
|
+
tailAngle3d,
|
|
439
|
+
bearingLong,
|
|
440
|
+
bearingLat,
|
|
441
|
+
centerCoords2dflat
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
//TODO free
|
|
448
|
+
free() {
|
|
449
|
+
if (this.isFreed) return;
|
|
450
|
+
this.bufferManagersCompMap.forEach(({ bufferManager, adaptor }) => {
|
|
451
|
+
bufferManager.free();
|
|
452
|
+
});
|
|
453
|
+
LineOnGlobeCache.release(this.globe);
|
|
454
|
+
pieceOfPieProgramCache.release(this.globe);
|
|
455
|
+
CircleCache.release(this.globe);
|
|
456
|
+
AngledLineProgramCache.release(this.globe);
|
|
457
|
+
this.isFreed = true;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
_insertTexts(item, textWriterInjectionSubSet) {
|
|
464
|
+
//TODO This method can be more performant if it works horizontally, tabular
|
|
465
|
+
textWriterInjectionSubSet.forEach((v) => {
|
|
466
|
+
const { coordsAdaptor, textAdaptor, writer } = v
|
|
467
|
+
const { lat, long } = coordsAdaptor(item);
|
|
468
|
+
const text = textAdaptor(item);
|
|
469
|
+
writer.insertText(item.key, lat, long, text);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
_deleteTexts(keys) {
|
|
475
|
+
this._textContextInjectionMap.forEach((e) => {
|
|
476
|
+
e.writer.deleteTextBulk(keys);
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
const radian = (degree) => degree * Math.PI / 180;
|
|
486
|
+
|
|
487
|
+
const integralSec = (angle) => {
|
|
488
|
+
return Math.log(Math.tan(angle / 2 + Math.PI / 4));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const textWriterGetOrThrow = mapGetOrThrow("BearingLine textContextInjection id does not exist in map")
|
|
492
|
+
|
|
493
|
+
const calculateStartAngle = (long, lat, endLong, endLat) => {
|
|
494
|
+
const dLat = (integralSec(endLat) - integralSec(lat)); // Because lines are strectes toward poles.
|
|
495
|
+
const dLong = endLong - long;
|
|
496
|
+
|
|
497
|
+
let angle = -Math.atan2(dLat, dLong);
|
|
498
|
+
return angle;
|
|
499
|
+
}
|
|
500
|
+
|