@pirireis/webglobeplugins 0.6.29-c → 0.6.30-c

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