@pirireis/webglobeplugins 0.6.17 → 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.
@@ -0,0 +1,430 @@
1
+ import { programCache as ringProgramCache } from '../partialrings/program';
2
+ import { LineOnGlobeCache } from '../programs/line-on-globe/naive';
3
+ import { CircleCache } from '../programs/line-on-globe/circle';
4
+ import { BufferOrchestrator, BufferManager } from '../util/account';
5
+ import { AngledLineProgramCache } from '../programs/line-on-globe/angled-line';
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
+
20
+
21
+ /**
22
+ * @typedef {Object}textContextInjection
23
+ * @property {string} id
24
+ * @property {function} coordsAdaptor
25
+ * @property {function} textAdaptor
26
+ * @property {ContextTextWriter} writer
27
+ *
28
+ */
29
+
30
+ export default class Plugin {
31
+ /**
32
+ *
33
+ * @param {*} id
34
+ * @param {Map<[K ,{writer:ContextTextWriter, coordsAdaptor, textAdaptor}]} textContextInjectionMap import { ContextTextWriter } from '@pirireis/webglobeplugins/write-text/context-text';
35
+ *
36
+ */
37
+
38
+ constructor(id, { opacity = 1, textContextInjectionMap = new Map(), drawVRM = true, drawBearingLine = true, drawAngleRing = true, drawText = true } = {}) {
39
+ this.id = id;
40
+ this._opacity = opacity;
41
+ this.bufferOrchestrator = new BufferOrchestrator({ capacity: 10 });
42
+ this._checkTextContextInjectionMap(textContextInjectionMap);
43
+ this._textContextInjectionMap = textContextInjectionMap;
44
+ this.drawVRM = drawVRM;
45
+ this.drawBearingLine = drawBearingLine;
46
+ this.drawAngleRing = drawAngleRing;
47
+ this.drawText = drawText;
48
+ }
49
+
50
+ setDoDrawVRM(bool) {
51
+ if (bool === this.drawVRM) return;
52
+ this.drawVRM = bool;
53
+ this.globe.DrawRender();
54
+ }
55
+
56
+ setDoDrawText(bool) {
57
+ if (bool === this.drawText) return;
58
+ this.drawText = bool;
59
+ this.globe.DrawRender();
60
+ }
61
+
62
+ setDoDrawText(bool) {
63
+ if (bool === this.drawText) return;
64
+ this.drawText = bool;
65
+ this.globe.DrawRender();
66
+ }
67
+
68
+ _checkTextContextInjectionMap(textContextInjectionMap) {
69
+ if (!(textContextInjectionMap instanceof Map)) throw new TypeError("textContextInjectionMap is not instance of Map");
70
+ textContextInjectionMap.forEach((v) => {
71
+ if (typeof v !== 'object') throw new TypeError("textContextInjectionMap format is wrong");
72
+ if (typeof v.coordsAdaptor !== 'function') throw new TypeError("textContextInjectionMap coordsAdaptor format is wrong");
73
+ if (typeof v.textAdaptor !== 'function') throw new TypeError("textContextInjectionMap textAdaptor format is wrong");
74
+ if (!(v.writer instanceof ContextTextWriter)) throw new TypeError("textContextInjectionMap writer is not instance of ContextTextWriter");
75
+ })
76
+ }
77
+
78
+ setDoDrawAngleRing(bool) {
79
+ if (bool === this.drawAngleRing) return;
80
+ this.drawAngleRing = bool;
81
+ this.globe.DrawRender();
82
+ }
83
+
84
+
85
+ settextContextInjectionMap(textContextInjectionMap, data = null) {
86
+ this._textContextInjectionMap = textContextInjectionMap;
87
+ this._textContextInjectionMap.forEach(({ writer }) => writer.clear());
88
+ if (data) {
89
+ for (const item of data) {
90
+ this._insertTexts(item);
91
+ }
92
+ }
93
+ }
94
+
95
+
96
+ setOpacity(opacity) {
97
+ constraintFloat(opacity, 0, 1);
98
+ this._opacity = opacity;
99
+ this._textContextInjectionMap.forEach(({ writer }) => writer.setOpacity(opacity));
100
+ this.globe.DrawRender();
101
+ }
102
+
103
+
104
+
105
+
106
+ init(globe, gl) {
107
+ this.gl = gl;
108
+ this.globe = globe;
109
+ this.lineProgram = LineOnGlobeCache.get(globe);
110
+ this.ringProgram = ringProgramCache.get(globe);
111
+ this.angledLineProgram = AngledLineProgramCache.get(globe);
112
+ this.circleProgram = CircleCache.get(globe);
113
+ // this.angleTextContext = new ContextTextWriter(globe);
114
+ // this.distanceTextContext = new ContextTextWriter(globe);
115
+ {
116
+ // createBuffers
117
+ const bufferType = "DYNAMIC_DRAW";
118
+ const initialCapacity = this.bufferOrchestrator.capacity;
119
+ this.bufferManagersCompMap = new Map(
120
+ [
121
+ ["centerCoords", {
122
+ 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
123
+ 'adaptor': (item) => new Float32Array([item.long, item.lat]),
124
+ }],
125
+ ["targetCoords", {
126
+ 'bufferManager': new BufferManager(gl, 2, { bufferType, initialCapacity }),
127
+ 'adaptor': (item) => new Float32Array([item.endLong, item.endLat])
128
+ }],
129
+ ["startAngle", {
130
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
131
+ 'adaptor': (item) => new Float32Array([item.startAngle])
132
+ }],
133
+ ["tailAngle", {
134
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
135
+ 'adaptor': (item) => new Float32Array([item.tailAngle])
136
+ }],
137
+ ["rgba", {
138
+ 'bufferManager': new BufferManager(gl, 4, { bufferType, initialCapacity }),
139
+ 'adaptor': (item) => new Float32Array(item.rgba)
140
+ }],
141
+ ["radius", {
142
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
143
+ 'adaptor': (item) => new Float32Array([item.radius])
144
+ }],
145
+ ["rgbaMode", {
146
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
147
+ 'adaptor': (item) => new Float32Array([item.rgbaMode])
148
+ }],
149
+ ["dashRatio", {
150
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
151
+ 'adaptor': (item) => new Float32Array([item.dashRatio])
152
+ }],
153
+ ["bearingAngle", {
154
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
155
+ 'adaptor': (item) => new Float32Array([item.bearingAngle])
156
+ }],
157
+ ["bigRadius", {
158
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
159
+ 'adaptor': (item) => new Float32Array([item.bigRadius])
160
+ }],
161
+ ["dashOpacity", {
162
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
163
+ 'adaptor': (item) => new Float32Array([item.dashOpacity])
164
+ }],
165
+ ["circleDashAngle", {
166
+ 'bufferManager': new BufferManager(gl, 1, { bufferType, initialCapacity }),
167
+ 'adaptor': (item) => new Float32Array([item.circleDashAngle / 360])
168
+ }]
169
+ ]
170
+ );
171
+ }
172
+
173
+
174
+ const obj = function (bufferManagerComp) {
175
+ return { 'buffer': bufferManagerComp.bufferManager.buffer, 'stride': 0, 'offset': 0 }
176
+ };
177
+
178
+ this.lineVao = this.lineProgram.createVAO(
179
+ ...['centerCoords', 'targetCoords', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
180
+ this.ringVao = this.ringProgram.createVAO(
181
+ ...['centerCoords', 'startAngle', 'tailAngle', 'rgba', 'radius', 'rgbaMode'].map(key => obj(this.bufferManagersCompMap.get(key))));
182
+ {
183
+ const angledLineBuffers = ["centerCoords", "bearingAngle", "bigRadius", "rgba", "dashRatio"].map(key => obj(this.bufferManagersCompMap.get(key)));
184
+ // dashOpacity is same as rgba.a to eleminate effect of dashOpacity.
185
+ const colorBuffer = this.bufferManagersCompMap.get("rgba");
186
+ angledLineBuffers.push(
187
+ { 'buffer': colorBuffer.bufferManager.buffer, 'stride': 16, 'offset': 12 },
188
+ )
189
+ this.angledLineVao = this.angledLineProgram.createVAO(...angledLineBuffers);
190
+ }
191
+ // centerObj, startAngleObj, radiusObj, colorObj, dashRatioObj, dashOpacityObj
192
+ this.circleVao = this.circleProgram.createVAO(
193
+ ...["centerCoords", "bigRadius", "rgba", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key))));
194
+ }
195
+
196
+
197
+
198
+ draw3D() {
199
+ const { gl } = this;
200
+ this.lineProgram.draw(this.lineVao, this.bufferOrchestrator.length, this._opacity);
201
+ gl.disable(gl.DEPTH_TEST);
202
+ if (this.drawAngleRing) {
203
+ this.ringProgram.draw(this.bufferOrchestrator.length, this.ringVao, 360, this._opacity * 0.8, RINGPARTIAL_DRAW_MODE.TRIANGLE_FAN);
204
+ this.ringProgram.draw(this.bufferOrchestrator.length, this.ringVao, 360, this._opacity, RINGPARTIAL_DRAW_MODE.LINE_STRIP);
205
+ }
206
+ if (this.drawBearingLine) {
207
+ this.angledLineProgram.draw(this.angledLineVao, this.bufferOrchestrator.length, this._opacity * 0.8);
208
+ }
209
+ if (this.drawVRM) {
210
+ this.circleProgram.draw(this.circleVao, this.bufferOrchestrator.length, this._opacity);
211
+ }
212
+ if (this.drawText) {
213
+ this._textContextInjectionMap.forEach((e) => { e.writer.draw(); });
214
+ }
215
+ gl.enable(gl.DEPTH_TEST);
216
+ }
217
+
218
+
219
+ /**
220
+ * @typedef {{key, long, lat, endLong, endLat, bearingAngle, radius, rgba:[4numbers], rgbaMode, bigRadius, dashRatio, dashOpacity, circleDashAngle}} item
221
+ * @property {string} key
222
+ * @property {number} long
223
+ * @property {number} lat
224
+ * @property {number} endLong
225
+ * @property {number} endLat
226
+ * @property {number} bearingAngle 0-360
227
+ * @property {number} radius angle ring radius
228
+ * @property {Array<4numbers>} rgba [r,g,b,a]
229
+ * @property {number} rgbaMode 0 constant, 1 fading, 2 hides angle ring
230
+ * @property {number} bigRadius undefined means it will be calculated from long, lat, endLong, endLat
231
+ * @property {number} dashRatio 0-1
232
+ * @property {number} dashOpacity 0-1
233
+ * @property {number} circleDashAngle 0-360
234
+ * @param {Array<item>} items
235
+ * @param {Array<string>} textWriterInjectionSubSetIDs | textContextInjectionMap keys to be used for writing text.
236
+ */
237
+ insertBulk(items, textWriterInjectionSubSetIDs = []) {
238
+ const { globe, bufferOrchestrator, bufferManagersCompMap } = this;// angleTextContext, distanceTextContext,
239
+ const textWriterInjectionSubSets = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);
240
+ const data = []
241
+ for (let item of items) {
242
+ this._insertTexts(item, textWriterInjectionSubSets);
243
+ data.push(this.__insertAdaptor(item));
244
+ }
245
+ bufferOrchestrator.insertBulk(data, bufferManagersCompMap);
246
+ this._textContextInjectionMap.forEach((v) => {
247
+ const { writer } = v;
248
+ writer.updateOpacityBulk(items, (e) => e.key, (e) => e.rgba[3]);
249
+ })
250
+ globe.DrawRender();
251
+ }
252
+
253
+
254
+
255
+
256
+ deleteBulk(keys) {
257
+ this.bufferOrchestrator.deleteBulk(keys, this.bufferManagersCompMap, ["radius", "centerCoords", "targetCoords", "rgba"]);
258
+ this._deleteTexts(keys);
259
+ this.globe.DrawRender();
260
+ }
261
+
262
+
263
+ defrag() {
264
+ this.bufferOrchestrator.defrag(this.bufferManagersCompMap);
265
+ }
266
+
267
+ /**
268
+ *
269
+ * @param {Array<{key, long, lat, endLong, endLat, bearingAngle}>} items
270
+ * @param {Array<string>} textWriterInjectionSubSetIDs | textContextInjectionMap keys to be used for writing text.
271
+ */
272
+ updateCoordinatesBulk(items, textWriterInjectionSubSetIDs = []) { //TODO
273
+ const injectionsSubSet = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);;
274
+ const { globe, bufferOrchestrator, bufferManagersCompMap, } = this;
275
+ const data = []
276
+ for (let item of items) {
277
+ this._insertTexts(item, injectionsSubSet);
278
+ data.push(this.__updateCoordsAdaptor(item));
279
+ }
280
+
281
+ bufferOrchestrator.updateBulk(data, bufferManagersCompMap, ["centerCoords", "targetCoords", "startAngle", "tailAngle", "bearingAngle", "bigRadius", "radius"]);
282
+ globe.DrawRender();
283
+ }
284
+
285
+
286
+ /**
287
+ *
288
+ * @param {*} items some colums EXCEPT positional ones
289
+ * @param {string} propertyIDs
290
+ * @param {string} textWriterInjectionSubSetIDs
291
+ * 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.
292
+ */
293
+ updatePartial(items, propertyIDs = [], textWriterInjectionSubSetIDs = []) { // textWriterInjectionSubSetIDs = []
294
+ if (propertyIDs.length === 0) console.warn("updatePartial is called with no target propertyIDs");
295
+ const { _textContextInjectionMap, bufferOrchestrator, bufferManagersCompMap } = this;
296
+ const writers = textWriterGetOrThrow(this._textContextInjectionMap, textWriterInjectionSubSetIDs);
297
+ for (let item of items) { this._insertTexts(item, writers) }
298
+ bufferOrchestrator.updateBulk(items, bufferManagersCompMap, propertyIDs);
299
+ // patch to update text opacity
300
+ for (const property of propertyIDs) {
301
+ if (property === "rgba") {
302
+ _textContextInjectionMap.forEach((v) => {
303
+ const { writer } = v;
304
+ writer.updateOpacityBulk(items, (e) => e.key, (e) => e.rgba[3]);
305
+ })
306
+ }
307
+ }
308
+ this.globe.DrawRender();
309
+ }
310
+
311
+
312
+ __insertAdaptor(item) {
313
+ const lat = radian(item.lat)
314
+ const long = radian(item.long)
315
+ const endLat = radian(item.endLat)
316
+ const endLong = radian(item.endLong)
317
+ const rgba = item.rgba !== undefined ? item.rgba : [0, 0, 0, 0];
318
+ const rgbaMode = item.rgbaMode !== undefined ? item.rgbaMode : 0;
319
+ const dashRatio = item.dashRatio !== undefined ? item.dashRatio : 1.0;
320
+ const dashOpacity = item.dashOpacity !== undefined ? item.dashOpacity : 0.9;
321
+ const circleDashAngle = item.circleDashAngle !== undefined ? item.circleDashAngle : 360;
322
+ const bigRadius = item.bigRadius !== undefined ? item.bigRadius : this.globe.Math.GetDist3D(item.long, item.lat, item.endLong, item.endLat);
323
+ const radius = item.radius !== undefined ? item.radius : bigRadius * 0.2;
324
+ const startAngle = calculateStartAngle(long, lat, endLong, endLat);
325
+ const bearingAngle = radian(item.bearingAngle - 90);
326
+ let tailAngle = bearingAngle - startAngle;
327
+ if (tailAngle > 0) {
328
+ tailAngle -= Math.PI * 2;
329
+ }
330
+ return {
331
+ key: item.key,
332
+ lat,
333
+ long,
334
+ endLat,
335
+ endLong,
336
+ bearingAngle,
337
+ radius,
338
+ bigRadius,
339
+ startAngle,
340
+ tailAngle,
341
+ rgba,
342
+ dashRatio,
343
+ dashOpacity,
344
+ circleDashAngle,
345
+ rgbaMode
346
+ };
347
+ }
348
+
349
+ __updateCoordsAdaptor(item) {
350
+ const lat = radian(item.lat)
351
+ const long = radian(item.long)
352
+ const endLat = radian(item.endLat)
353
+ const endLong = radian(item.endLong)
354
+ const bigRadius = item.bigRadius !== undefined ? item.bigRadius : this.globe.Math.GetDist3D(item.long, item.lat, item.endLong, item.endLat);
355
+ const radius = item.radius !== undefined ? item.radius : bigRadius * 0.2;
356
+ const startAngle = calculateStartAngle(long, lat, endLong, endLat);
357
+ const bearingAngle = radian(item.bearingAngle - 90);
358
+ let tailAngle = bearingAngle - startAngle;
359
+ if (tailAngle > 0) {
360
+ tailAngle -= Math.PI * 2;
361
+ }
362
+ return {
363
+ key: item.key,
364
+ lat,
365
+ long,
366
+ endLat,
367
+ endLong,
368
+ bearingAngle,
369
+ radius,
370
+ bigRadius,
371
+ startAngle,
372
+ tailAngle,
373
+ };
374
+ }
375
+
376
+
377
+ //TODO free
378
+ free() {
379
+ if (this.isFreed) return;
380
+ this.bufferManagersCompMap.forEach(({ bufferManager, adaptor }) => {
381
+ bufferManager.free();
382
+ });
383
+ LineOnGlobeCache.release(this.globe);
384
+ ringProgramCache.release(this.globe);
385
+ CircleCache.release(this.globe);
386
+ AngledLineProgramCache.release(this.globe);
387
+ this.isFreed = true;
388
+ }
389
+
390
+
391
+
392
+
393
+ _insertTexts(item, textWriterInjectionSubSet) {
394
+ //TODO This method can be more performant if it works horizontally, tabular
395
+ textWriterInjectionSubSet.forEach((v) => {
396
+ const { coordsAdaptor, textAdaptor, writer } = v
397
+ const { lat, long } = coordsAdaptor(item);
398
+ const text = textAdaptor(item);
399
+ writer.insertText(item.key, lat, long, text);
400
+ });
401
+ }
402
+
403
+
404
+ _deleteTexts(keys) {
405
+ this._textContextInjectionMap.forEach((e) => {
406
+ e.writer.deleteTextBulk(keys);
407
+ });
408
+ }
409
+
410
+
411
+ }
412
+
413
+
414
+
415
+ const radian = (degree) => degree * Math.PI / 180;
416
+
417
+ const integralSec = (angle) => {
418
+ return Math.log(Math.tan(angle / 2 + Math.PI / 4));
419
+ }
420
+
421
+ const textWriterGetOrThrow = mapGetOrThrow("BearingLine textContextInjection id does not exist in map")
422
+
423
+ const calculateStartAngle = (long, lat, endLong, endLat) => {
424
+ const dLat = (integralSec(endLat) - integralSec(lat)); // Because lines are strectes toward poles.
425
+ const dLong = endLong - long;
426
+
427
+ let angle = -Math.atan2(dLat, dLong);
428
+ return angle;
429
+ }
430
+
@@ -1,10 +1,12 @@
1
1
  import { LineOnGlobeCache } from '../programs/line-on-globe/naive-accurate';
2
- import { CircleCache } from '../programs/line-on-globe/circle-accurate';
2
+ import { CircleCache, EDGE_COUNT as EDGE_COUNT_2D_CIRCLE, centerCoords2dflatDataCreator } from '../programs/line-on-globe/circle-accurate-flat';
3
+ import { CircleCache as Circle3DCache } from '../programs/line-on-globe/circle-accurate-3d';
3
4
  import { LineToTheOriginCache } from "../programs/line-on-globe/to-the-origin"
4
5
  import { BufferOrchestrator, BufferManager } from "../util/account";
5
6
  import { ChainListMap } from "./chain-list-map";
6
7
  import { mapGetOrThrow } from "../util/check/get";
7
8
  import { keyMethod } from "./util";
9
+ import { populateFloat32Array } from "../util/jshelpers/data-filler";
8
10
  import { ContextTextWriter3 } from '../write-text/context-text3';
9
11
  // TODO: Add update buffer and update text mehods on add, delete, update methods
10
12
 
@@ -76,7 +78,9 @@ export class CircleLineChainPlugin {
76
78
  _initOrchestrations() {
77
79
  const { gl, globe } = this;
78
80
  this.lineProgram = LineOnGlobeCache.get(globe);
79
- this.circleProgram = CircleCache.get(globe);
81
+ this.circleProgram2d = CircleCache.get(globe);
82
+ this.circle3DProgram = Circle3DCache.get(globe);
83
+
80
84
  this.lineToTheOriginProgram = LineToTheOriginCache.get(globe);
81
85
  {
82
86
  // createBuffers
@@ -133,7 +137,32 @@ export class CircleLineChainPlugin {
133
137
  if (item.circleProperties?.rgba) return new Float32Array(item.circleProperties.rgba);
134
138
  return new Float32Array(item.chainProperties.rgba);
135
139
  }
136
- }]
140
+ }],
141
+
142
+
143
+ // Mercator buffers
144
+ ["circleDashAngleMercator", {
145
+ 'bufferManager': new BufferManager(gl, 1 * EDGE_COUNT_2D_CIRCLE, { bufferType, initialCapacity }),
146
+ 'adaptor': (item) => {
147
+ if (item.circleProperties?.circleDashAngle) return new Float32Array([item.circleProperties.circleDashAngle / 360]);
148
+ return new populateFloat32Array.fillFloat32Array(EDGE_COUNT_2D_CIRCLE, item.chainProperties.circleDashAngle / 360);
149
+ }
150
+ }],
151
+ ["rgbaCircleMercator", {
152
+ "bufferManager": new BufferManager(gl, 4 * EDGE_COUNT_2D_CIRCLE, { bufferType, initialCapacity }),
153
+ "adaptor": (item) => {
154
+ if (item.circleProperties?.rgba) return populateFloat32Array.fillWithListData(EDGE_COUNT_2D_CIRCLE, item.circleProperties.rgba);
155
+ return populateFloat32Array.fillWithListData(EDGE_COUNT_2D_CIRCLE, item.chainProperties.rgba);
156
+ }
157
+ }],
158
+ ["dashOpacityMercator", {
159
+ 'bufferManager': new BufferManager(gl, 1 * EDGE_COUNT_2D_CIRCLE, { bufferType, initialCapacity }),
160
+ 'adaptor': (item) => populateFloat32Array.fillFloat32Array(EDGE_COUNT_2D_CIRCLE, item.chainProperties.dashOpacity)
161
+ }],
162
+ ["centerCoords2dMercator", {
163
+ 'bufferManager': new BufferManager(gl, 2 * EDGE_COUNT_2D_CIRCLE, { bufferType, initialCapacity }),
164
+ 'adaptor': (item) => item.centerCoords2dflat,
165
+ }],
137
166
  ]
138
167
  );
139
168
  // (startPotisionBufferObj, endPositionBufferObj, dashRatioBufferObj, colorBufferObj)
@@ -142,10 +171,14 @@ export class CircleLineChainPlugin {
142
171
  };
143
172
  this.lineVao = this.lineProgram.createVAO(
144
173
  ...['centerCoords2d', 'centerCoords3d', 'targetCoords2d', 'targetCoords3d', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
145
- this.circleVao = this.circleProgram.createVAO(
146
- ...["centerCoords2d", "centerCoords3d", "bigRadius", "rgbaCircle", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key))));
174
+ this.circleVao2d = this.circleProgram2d.createVAO(
175
+ ...["centerCoords2dMercator", "rgbaCircleMercator", "circleDashAngleMercator", "dashOpacityMercator"].map(key => obj(this.bufferManagersCompMap.get(key))));
147
176
  this.toOriginVao = this.lineToTheOriginProgram.createVAO(
148
177
  ...["targetCoords3d", "rgba"].map(key => obj(this.bufferManagersCompMap.get(key))));
178
+ this.circle3DVao = this.circle3DProgram.createVAO(
179
+ ...["centerCoords3d", "bigRadius", "rgbaCircle", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key)))
180
+ );
181
+
149
182
  }
150
183
 
151
184
  }
@@ -338,13 +371,16 @@ export class CircleLineChainPlugin {
338
371
  const { globe } = this;
339
372
  // this.lineVao = this.lineProgram.createVAO(
340
373
  // ...['centerCoords', 'targetCoords', 'dashRatio', 'dashOpacity', 'rgba'].map(key => obj(this.bufferManagersCompMap.get(key))));
341
- // this.circleVao = this.circleProgram.createVAO(
374
+ // this.circleVao2d = this.circleProgram2d.createVAO(
342
375
  // ...["centerCoords", "bigRadius", "rgba", "circleDashAngle", "dashOpacity"].map(key => obj(this.bufferManagersCompMap.get(key))));
343
376
  // }
344
377
 
345
378
  const radiusM = radiusMethod(globe);
346
379
  const callback = (v, i, array, chainProperties) => {
347
380
  if (i == array.length - 1) return null;
381
+
382
+ const centerCoords2dflat = centerCoords2dflatDataCreator(globe, v.long, v.lat, array[i + 1].long, array[i + 1].lat);
383
+
348
384
  return {
349
385
  chainProperties: chainProperties,
350
386
  bigRadius: radiusM(v, i, array),
@@ -354,7 +390,9 @@ export class CircleLineChainPlugin {
354
390
  lat: v.lat,
355
391
  lineProperties: v.lineProperties,
356
392
  circleProperties: v.circleProperties,
393
+ centerCoords2dflat,
357
394
  key: v.__identity__
395
+
358
396
  }
359
397
  }
360
398
  const bulkData = [];
@@ -381,8 +419,15 @@ export class CircleLineChainPlugin {
381
419
  })
382
420
  LineOnGlobeCache.release(this.globe);
383
421
  CircleCache.release(this.globe);
422
+ Circle3DCache.release(this.globe);
423
+ LineToTheOriginCache.release(this.globe);
424
+ this._textContextWriterInjectionMap.forEach((writer) => writer.free());
425
+ const { gl } = this;
426
+ gl.deleteVertexArray(this.lineVao);
427
+ gl.deleteVertexArray(this.circleVao2d);
428
+ gl.deleteVertexArray(this.toOriginVao);
384
429
  this.lineProgram = null;
385
- this.circleProgram = null;
430
+ this.circleProgram2d = null;
386
431
  this.isFreed = true;
387
432
  }
388
433
 
@@ -390,9 +435,16 @@ export class CircleLineChainPlugin {
390
435
  const { gl, globe } = this;
391
436
  gl.disable(gl.DEPTH_TEST);
392
437
  this.lineProgram.draw(this.lineVao, this.bufferOrchestrator.length, this._opacity);
393
- if (this._drawCircleOn) this.circleProgram.draw(this.circleVao, this.bufferOrchestrator.length, this._opacity);
394
438
  this._textContextWriterInjectionMap.forEach((writer) => writer.draw());
395
439
  this.lineToTheOriginProgram.draw(this.toOriginVao, this.bufferOrchestrator.length, this._opacity);
440
+ const is3D = globe.api_GetCurrentGeometry() === 0;
441
+ if (this._drawCircleOn) {
442
+ if (is3D) {
443
+ this.circle3DProgram.draw(this.circle3DVao, this.bufferOrchestrator.length, this._opacity);
444
+ } else {
445
+ this.circleProgram2d.draw(this.circleVao2d, this.bufferOrchestrator.length, this._opacity);
446
+ }
447
+ }
396
448
  gl.enable(gl.DEPTH_TEST);
397
449
  }
398
450
  }