@openglobus/og 0.13.10 → 0.14.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.
Files changed (83) hide show
  1. package/README.md +1 -4
  2. package/css/og.css +1 -1
  3. package/dist/@openglobus/og.css +1 -1
  4. package/dist/@openglobus/og.esm.js +2 -2
  5. package/dist/@openglobus/og.esm.js.map +1 -1
  6. package/dist/@openglobus/og.umd.js +2 -2
  7. package/dist/@openglobus/og.umd.js.map +1 -1
  8. package/package.json +2 -2
  9. package/src/og/Globe.js +14 -4
  10. package/src/og/camera/Camera.js +7 -7
  11. package/src/og/camera/PlanetCamera.js +1 -1
  12. package/src/og/control/LayerSwitcher.js +48 -31
  13. package/src/og/control/MouseNavigation.js +2 -2
  14. package/src/og/control/ScaleControl.js +30 -10
  15. package/src/og/control/SimpleSkyBackground.js +184 -0
  16. package/src/og/control/Sun.js +3 -2
  17. package/src/og/ellipsoid/Ellipsoid.js +119 -92
  18. package/src/og/ellipsoid/wgs84.js +13 -13
  19. package/src/og/entity/Entity.js +3 -3
  20. package/src/og/entity/GeometryHandler.js +1341 -1337
  21. package/src/og/entity/LabelHandler.js +1 -4
  22. package/src/og/entity/LabelWorker.js +10 -13
  23. package/src/og/entity/Polyline.js +0 -16
  24. package/src/og/entity/Ray.js +0 -10
  25. package/src/og/entity/RayHandler.js +3 -44
  26. package/src/og/entity/Strip.js +1 -6
  27. package/src/og/index.js +106 -95
  28. package/src/og/layer/GeoVideo.js +1 -0
  29. package/src/og/layer/Layer.js +62 -3
  30. package/src/og/layer/XYZ.js +4 -3
  31. package/src/og/math/Line3.js +140 -139
  32. package/src/og/math/Plane.js +118 -117
  33. package/src/og/math/Ray.js +242 -239
  34. package/src/og/math/Vec3.js +56 -37
  35. package/src/og/math/Vec4.js +3 -4
  36. package/src/og/math.js +21 -21
  37. package/src/og/quadTree/EarthQuadTreeStrategy.js +29 -0
  38. package/src/og/quadTree/MarsQuadTreeStrategy.js +27 -0
  39. package/src/og/quadTree/Node.js +55 -218
  40. package/src/og/quadTree/QuadTreeStrategy.js +93 -0
  41. package/src/og/quadTree/Wgs84QuadTreeStrategy.js +26 -0
  42. package/src/og/renderer/Renderer.js +13 -12
  43. package/src/og/renderer/RendererEvents.js +1065 -1065
  44. package/src/og/scene/Planet.js +84 -273
  45. package/src/og/segment/Segment.js +18 -25
  46. package/src/og/segment/SegmentLonLat.js +34 -31
  47. package/src/og/segment/SegmentLonLatWgs84.js +41 -0
  48. package/src/og/shaders/ray.js +13 -6
  49. package/src/og/shaders/toneMapping.js +5 -5
  50. package/src/og/terrain/GlobusTerrain.js +3 -2
  51. package/src/og/terrain/MapboxTerrain.js +231 -52
  52. package/src/og/utils/quadTreeType.js +11 -0
  53. package/src/og/utils/shared.js +942 -942
  54. package/src/og/webgl/Handler.js +22 -9
  55. package/types/Globe.d.ts +7 -0
  56. package/types/camera/Camera.d.ts +3 -3
  57. package/types/camera/PlanetCamera.d.ts +1 -1
  58. package/types/control/LayerSwitcher.d.ts +1 -1
  59. package/types/control/ScaleControl.d.ts +2 -1
  60. package/types/control/SimpleSkyBackground.d.ts +11 -0
  61. package/types/control/Sun.d.ts +2 -1
  62. package/types/ellipsoid/Ellipsoid.d.ts +3 -2
  63. package/types/entity/LabelWorker.d.ts +1 -1
  64. package/types/entity/Ray.d.ts +0 -3
  65. package/types/entity/RayHandler.d.ts +0 -4
  66. package/types/index.d.ts +6 -1
  67. package/types/layer/Layer.d.ts +8 -0
  68. package/types/math/Vec3.d.ts +19 -16
  69. package/types/math/Vec4.d.ts +2 -3
  70. package/types/math.d.ts +20 -20
  71. package/types/quadTree/EarthQuadTreeStrategy.d.ts +3 -0
  72. package/types/quadTree/MarsQuadTreeStrategy.d.ts +3 -0
  73. package/types/quadTree/Node.d.ts +0 -1
  74. package/types/quadTree/QuadTreeStrategy.d.ts +21 -0
  75. package/types/quadTree/Wgs84QuadTreeStrategy.d.ts +3 -0
  76. package/types/renderer/Renderer.d.ts +1 -1
  77. package/types/scene/Planet.d.ts +6 -24
  78. package/types/segment/Segment.d.ts +4 -4
  79. package/types/segment/SegmentLonLat.d.ts +6 -2
  80. package/types/segment/SegmentLonLatWgs84.d.ts +4 -0
  81. package/types/terrain/MapboxTerrain.d.ts +2 -1
  82. package/types/utils/quadTreeType.d.ts +8 -0
  83. package/types/webgl/Handler.d.ts +4 -1
@@ -1,943 +1,943 @@
1
- /**
2
- * @module og/utils/shared
3
- */
4
-
5
- "use strict";
6
-
7
- import { ajax } from "../ajax.js";
8
- import { colorTable } from "./colorTable.js";
9
- import { Extent } from "../Extent.js";
10
- import { LonLat } from "../LonLat.js";
11
- import { Vec2 } from "../math/Vec2.js";
12
- import { Vec3 } from "../math/Vec3.js";
13
- import { Vec4 } from "../math/Vec4.js";
14
-
15
- export function getDefault(param, def) {
16
- return param != undefined ? param : def;
17
- }
18
-
19
- export function isEmpty(v) {
20
- return v == null;
21
- }
22
-
23
- let _stampCounter = 0;
24
-
25
- export function stamp(obj) {
26
- var stamp = obj._openglobus_id;
27
- if (!stamp) {
28
- stamp = obj._openglobus_id = ++_stampCounter;
29
- }
30
- return stamp;
31
- }
32
-
33
- export function isString(s) {
34
- return typeof s === "string" || s instanceof String;
35
- }
36
-
37
- /**
38
- * Synchronous text file loading. Returns file text.
39
- * @param {string} fileUrl - File name path.
40
- * @returns {string} -
41
- */
42
- export function readTextFile(fileUrl) {
43
- var res = "";
44
-
45
- ajax.request(fileUrl, {
46
- async: false,
47
- success: function (data) {
48
- res = data;
49
- }
50
- });
51
-
52
- return res;
53
- }
54
-
55
- /**
56
- * Convert html color string to the RGBA number vector.
57
- * @param {string} htmlColor - HTML string("#C6C6C6" or "#EF5" or "rgb(8,8,8)" or "rgba(8,8,8)") color.
58
- * @param {number} [opacity] - Opacity for the output vector.
59
- * @returns {math.Vec4} -
60
- */
61
- export function htmlColorToRgba(htmlColor, opacity) {
62
- var hColor = colorTable[htmlColor];
63
- if (hColor) {
64
- htmlColor = hColor;
65
- }
66
-
67
- if (htmlColor[0] === "#") {
68
- var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
69
- var hex = htmlColor.replace(shorthandRegex, function (m, r, g, b) {
70
- return r + r + g + g + b + b;
71
- });
72
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
73
- return new Vec4(
74
- parseInt(result[1], 16) / 255,
75
- parseInt(result[2], 16) / 255,
76
- parseInt(result[3], 16) / 255,
77
- isEmpty(opacity) ? 1.0 : opacity
78
- );
79
- } else {
80
- if (isEmpty(opacity)) {
81
- opacity = 1.0;
82
- }
83
- var m = htmlColor.split(",");
84
- return new Vec4(
85
- parseInt(m[0].split("(")[1]) / 255,
86
- parseInt(m[1]) / 255,
87
- parseInt(m[2]) / 255,
88
- !isEmpty(m[3]) ? parseFloat(m[3]) : opacity
89
- );
90
- }
91
- }
92
-
93
- export function htmlColorToFloat32Array(htmlColor, opacity) {
94
- let c = htmlColorToRgba(htmlColor, opacity);
95
- return new Float32Array([c.x, c.y, c.z, c.w]);
96
- }
97
-
98
- /**
99
- * Convert html color string to the RGB number vector.
100
- * @param {string} htmlColor - HTML string("#C6C6C6" or "#EF5" or "rgb(8,8,8)" or "rgba(8,8,8)") color.
101
- * @param {number} [opacity] - Opacity for the output vector.
102
- * @returns {Vec3} -
103
- */
104
- export function htmlColorToRgb(htmlColor) {
105
- var hColor = colorTable[htmlColor];
106
- if (hColor) {
107
- htmlColor = hColor;
108
- }
109
-
110
- if (htmlColor[0] === "#") {
111
- var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
112
- var hex = htmlColor.replace(shorthandRegex, function (m, r, g, b) {
113
- return r + r + g + g + b + b;
114
- });
115
- var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
116
- return new Vec4(
117
- parseInt(result[1], 16) / 255,
118
- parseInt(result[2], 16) / 255,
119
- parseInt(result[3], 16) / 255
120
- );
121
- } else {
122
- var m = htmlColor.split(",");
123
- return new Vec3(
124
- parseInt(m[0].split("(")[1]) / 255,
125
- parseInt(m[1]) / 255,
126
- parseInt(m[2]) / 255
127
- );
128
- }
129
- }
130
-
131
- /**
132
- * Replace template substrings between '{' and '}' tokens.
133
- * @param {string} template - String with templates in "{" and "}"
134
- * @param {Object} params - Template named object with subsrtings.
135
- * @returns {string} -
136
- *
137
- * @example <caption>Example from og.terrain that replaces tile indexes in url:</caption>
138
- * var substrings = {
139
- * "x": 12,
140
- * "y": 15,
141
- * "z": 8
142
- * }
143
- * og.utils.stringTemplate("http://earth3.openglobus.org/{z}/{y}/{x}.ddm", substrins);
144
- * //returns http://earth3.openglobus.org/8/15/12.ddm
145
- */
146
- export function stringTemplate(template, params) {
147
- return template.replace(/{[^{}]+}/g, function (key) {
148
- return params[key.replace(/[{}]+/g, "")] || "";
149
- });
150
- }
151
-
152
- export function getHTML(template, params) {
153
- return stringTemplate(template, params);
154
- }
155
-
156
- export function parseHTML(htmlStr) {
157
- var p = document.createElement("div");
158
- p.innerHTML = htmlStr;
159
- var domArr = [];
160
- for (var i = 0; i < p.childNodes.length; i++) {
161
- domArr.push(p.childNodes[i]);
162
- p.removeChild(p.childNodes[i]);
163
- }
164
- return domArr;
165
- }
166
-
167
- export function print2d(id, text, x, y) {
168
- var el = document.getElementById(id);
169
- if (!el) {
170
- el = document.createElement("div");
171
- el.id = id;
172
- el.classList.add("defaultText");
173
- document.body.appendChild(el);
174
- }
175
- el.innerHTML = text;
176
- el.style.left = x;
177
- el.style.top = y;
178
- }
179
-
180
- export function defaultString(str, def) {
181
- return str ? str.trim().toLowerCase() : def;
182
- }
183
-
184
- export function createVector3(v, def) {
185
- if (v) {
186
- if (v instanceof Vec3) {
187
- return v.clone();
188
- } else if (v instanceof Array) {
189
- return Vec3.fromVec(v);
190
- }
191
- } else if (def) {
192
- return def;
193
- }
194
- return new Vec3();
195
- }
196
-
197
- export function createVector4(v, def) {
198
- if (v) {
199
- if (v instanceof Vec4) {
200
- return v.clone();
201
- } else if (v instanceof Array) {
202
- return Vec4.fromVec(v);
203
- }
204
- } else if (def) {
205
- return def;
206
- }
207
- return new Vec4();
208
- }
209
-
210
- export function createColorRGBA(c, def) {
211
- if (c) {
212
- if (isString(c)) {
213
- return htmlColorToRgba(c);
214
- } else if (c instanceof Array) {
215
- return Vec4.fromVec(c);
216
- } else if (c instanceof Vec4) {
217
- return c.clone();
218
- }
219
- } else if (def) {
220
- return def;
221
- }
222
- return new Vec4(1.0, 1.0, 1.0, 1.0);
223
- }
224
-
225
- export function createColorRGB(c, def) {
226
- if (c) {
227
- if (isString(c)) {
228
- return htmlColorToRgb(c);
229
- } else if (c instanceof Array) {
230
- return Vec3.fromVec(c);
231
- } else if (c instanceof Vec3) {
232
- return c.clone();
233
- }
234
- } else if (def) {
235
- return def;
236
- }
237
- return new Vec3(1.0, 1.0, 1.0);
238
- }
239
-
240
- export function createExtent(e, def) {
241
- if (e) {
242
- if (e instanceof Array) {
243
- return new Extent(createLonLat(e[0]), createLonLat(e[1]));
244
- } else if (e instanceof Extent) {
245
- return e.clone();
246
- }
247
- } else if (def) {
248
- return def;
249
- }
250
- return new Extent();
251
- }
252
-
253
- export function createLonLat(l, def = null) {
254
- if (l) {
255
- if (l instanceof Array) {
256
- return new LonLat(l[0], l[1], l[2]);
257
- } else if (l instanceof LonLat) {
258
- return l.clone();
259
- }
260
- } else if (def) {
261
- return def;
262
- }
263
- return new LonLat();
264
- }
265
-
266
- export function binarySearchFast(arr, x) {
267
- let start = 0,
268
- end = arr.length - 1;
269
- while (start <= end) {
270
- let k = Math.floor((start + end) * 0.5);
271
- if (arr[k] === x) {
272
- return k;
273
- } else if (arr[k] < x) {
274
- start = k + 1;
275
- } else {
276
- end = k - 1;
277
- }
278
- }
279
- return -1;
280
- }
281
-
282
- /**
283
- * Finds an item in a sorted array.
284
- * @param {Array} ar The sorted array to search.
285
- * @param {Object} el The item to find in the array.
286
- * @param {utils.binarySearch~compare_fn} compare_fn comparator The function to use to compare the item to
287
- * elements in the array.
288
- * @returns {Number} a negative number if a is less than b; 0 if a is equal to b;a positive number of a is greater than b.
289
- *
290
- * @example
291
- * // Create a comparator function to search through an array of numbers.
292
- * function comparator(a, b) {
293
- * return a - b;
294
- * };
295
- * var numbers = [0, 2, 4, 6, 8];
296
- * var index = og.utils.binarySearch(numbers, 6, comparator); // 3
297
- */
298
- export function binarySearch(ar, el, compare_fn) {
299
- var m = 0;
300
- var n = ar.length - 1;
301
- while (m <= n) {
302
- var k = (n + m) >> 1;
303
- var cmp = compare_fn(el, ar[k], k);
304
- if (cmp > 0) {
305
- m = k + 1;
306
- } else if (cmp < 0) {
307
- n = k - 1;
308
- } else {
309
- return k;
310
- }
311
- }
312
- return -m - 1;
313
- }
314
-
315
- /**
316
- * Binary insertion that uses binarySearch algorithm.
317
- * @param {Array} ar - The sorted array to insert.
318
- * @param {Object} el - The item to insert.
319
- * @param {utils.binarySearch~compare_fn} compare_fn - comparator The function to use to compare the item to
320
- * elements in the array.
321
- * @returns {Number} Array index position in which item inserted in.
322
- */
323
- export function binaryInsert(ar, el, compare_fn) {
324
- var i = binarySearch(ar, el, compare_fn);
325
- if (i < 0) {
326
- i = ~i;
327
- }
328
- ar.splice(i, 0, el);
329
- return i;
330
- }
331
-
332
- /**
333
- * Returns two segment lines intersection coordinate.
334
- * @static
335
- * @param {math.Vec2} start1 - First line first coordinate.
336
- * @param {math.Vec2} end1 - First line second coordinate.
337
- * @param {math.Vec2} start2 - Second line first coordinate.
338
- * @param {math.Vec2} end2 - Second line second coordinate.
339
- * @param {boolean} [isSegment] - Lines are segments.
340
- * @return {math.Vec2} - Intersection coordinate.
341
- */
342
- export function getLinesIntersection2v(start1, end1, start2, end2, isSegment) {
343
- var dir1 = end1.sub(start1);
344
- var dir2 = end2.sub(start2);
345
-
346
- var a1 = -dir1.y;
347
- var b1 = +dir1.x;
348
- var d1 = -(a1 * start1.x + b1 * start1.y);
349
-
350
- var a2 = -dir2.y;
351
- var b2 = +dir2.x;
352
- var d2 = -(a2 * start2.x + b2 * start2.y);
353
-
354
- var seg1_line2_start = a2 * start1.x + b2 * start1.y + d2;
355
- var seg1_line2_end = a2 * end1.x + b2 * end1.y + d2;
356
-
357
- var seg2_line1_start = a1 * start2.x + b1 * start2.y + d1;
358
- var seg2_line1_end = a1 * end2.x + b1 * end2.y + d1;
359
-
360
- if (
361
- isSegment &&
362
- (seg1_line2_start * seg1_line2_end > 0 || seg2_line1_start * seg2_line1_end > 0)
363
- ) {
364
- return null;
365
- }
366
-
367
- var u = seg1_line2_start / (seg1_line2_start - seg1_line2_end);
368
-
369
- return new Vec2(start1.x + u * dir1.x, start1.y + u * dir1.y);
370
- }
371
-
372
- /**
373
- * Returns two segment lines intersection coordinate.
374
- * @static
375
- * @param {math.Vec2} start1 - First line first coordinate.
376
- * @param {math.Vec2} end1 - First line second coordinate.
377
- * @param {math.Vec2} start2 - Second line first coordinate.
378
- * @param {math.Vec2} end2 - Second line second coordinate.
379
- * @param {boolean} [isSegment] - Lines are segments.
380
- * @return {math.Vec2} - Intersection coordinate.
381
- */
382
- export function getLinesIntersectionLonLat(start1, end1, start2, end2, isSegment) {
383
- var dir1 = new LonLat(end1.lon - start1.lon, end1.lat - start1.lat);
384
- var dir2 = new LonLat(end2.lon - start2.lon, end2.lat - start2.lat);
385
-
386
- var a1 = -dir1.lat;
387
- var b1 = +dir1.lon;
388
- var d1 = -(a1 * start1.lon + b1 * start1.lat);
389
-
390
- var a2 = -dir2.lat;
391
- var b2 = +dir2.lon;
392
- var d2 = -(a2 * start2.lon + b2 * start2.lat);
393
-
394
- var seg1_line2_start = a2 * start1.lon + b2 * start1.lat + d2;
395
- var seg1_line2_end = a2 * end1.lon + b2 * end1.lat + d2;
396
-
397
- var seg2_line1_start = a1 * start2.lon + b1 * start2.lat + d1;
398
- var seg2_line1_end = a1 * end2.lon + b1 * end2.lat + d1;
399
-
400
- if (
401
- isSegment &&
402
- (seg1_line2_start * seg1_line2_end > 0 || seg2_line1_start * seg2_line1_end > 0)
403
- ) {
404
- return null;
405
- }
406
-
407
- var u = seg1_line2_start / (seg1_line2_start - seg1_line2_end);
408
-
409
- return new LonLat(start1.lon + u * dir1.lon, start1.lat + u * dir1.lat);
410
- }
411
-
412
- /**
413
- * Converts XML to JSON
414
- * @static
415
- * @param {Object} xml - Xml object
416
- * @return {Object} - Json converted object.
417
- */
418
- export function xmlToJson(xml) {
419
- // Create the return object
420
- var obj = {};
421
-
422
- if (xml.nodeType === 1) {
423
- // element
424
- // do attributes
425
- if (xml.attributes.length > 0) {
426
- obj["@attributes"] = {};
427
- for (var j = 0; j < xml.attributes.length; j++) {
428
- var attribute = xml.attributes.item(j);
429
- obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
430
- }
431
- }
432
- } else if (xml.nodeType === 3) {
433
- // text
434
- obj = xml.nodeValue;
435
- }
436
-
437
- // do children
438
- if (xml.hasChildNodes()) {
439
- for (var i = 0; i < xml.childNodes.length; i++) {
440
- var item = xml.childNodes.item(i);
441
- var nodeName = item.nodeName;
442
- if (typeof obj[nodeName] === "undefined") {
443
- obj[nodeName] = xmlToJson(item);
444
- } else {
445
- if (typeof obj[nodeName].push === "undefined") {
446
- var old = obj[nodeName];
447
- obj[nodeName] = [];
448
- obj[nodeName].push(old);
449
- }
450
- obj[nodeName].push(xmlToJson(item));
451
- }
452
- }
453
- }
454
- return obj;
455
- }
456
-
457
- export const castType = {
458
- string: function (v) {
459
- return isEmpty(v) ? v : v.toString();
460
- },
461
-
462
- date: function (v) {
463
- return isEmpty(v) ? v : new Date(v * 1000);
464
- },
465
-
466
- datetime: function (v) {
467
- return isEmpty(v) ? v : new Date(v * 1000);
468
- },
469
-
470
- time: function (v) {
471
- return isEmpty(v) ? v : parseInt(v);
472
- },
473
-
474
- integer: function (v) {
475
- return isEmpty(v) ? v : parseInt(v);
476
- },
477
-
478
- float: function (v) {
479
- return isEmpty(v) ? v : parseFloat(v);
480
- },
481
-
482
- boolean: function (str) {
483
- if (str === null) {
484
- return str;
485
- }
486
-
487
- if (typeof str === "boolean") {
488
- if (str === true) {
489
- return true;
490
- }
491
- return false;
492
- }
493
- if (typeof str === "string") {
494
- if (str === "") {
495
- return false;
496
- }
497
- str = str.replace(/^\s+|\s+$/g, "");
498
- if (str.toLowerCase() === "true" || str.toLowerCase() === "yes") {
499
- return true;
500
- }
501
- str = str.replace(/,/g, ".");
502
- str = str.replace(/^\s*\-\s*/g, "-");
503
- }
504
- if (!isNaN(str)) {
505
- return parseFloat(str) !== 0;
506
- }
507
- return false;
508
- }
509
- };
510
-
511
- export function base64toBlob(base64Data, contentType) {
512
- contentType = contentType || "";
513
- var sliceSize = 1024;
514
- var byteCharacters = atob(base64Data);
515
- var bytesLength = byteCharacters.length;
516
- var slicesCount = Math.ceil(bytesLength / sliceSize);
517
- var byteArrays = new Array(slicesCount);
518
-
519
- for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
520
- var begin = sliceIndex * sliceSize;
521
- var end = Math.min(begin + sliceSize, bytesLength);
522
-
523
- var bytes = new Array(end - begin);
524
- for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
525
- bytes[i] = byteCharacters[offset].charCodeAt(0);
526
- }
527
- byteArrays[sliceIndex] = new Uint8Array(bytes);
528
- }
529
- return new Blob(byteArrays, { type: contentType });
530
- }
531
-
532
- export function base64StringToBlog(string) {
533
- let block = string.split(";");
534
- let contentType = block[0].split(":")[1];
535
- let data = block[1].split(",")[1];
536
-
537
- return base64toBlob(data, contentType);
538
- }
539
-
540
- ///**
541
- // *
542
- // * @param {LonLat} p
543
- // * @param {LonLat} v1
544
- // * @param {LonLat} v2
545
- // * @param {LonLat} v3
546
- // * @param {Array<Number>} res
547
- // */
548
- //export function cartesianToBarycentricLonLat(p, v1, v2, v3, res) {
549
-
550
- // const y2y3 = v2.lat - v3.lat,
551
- // x3x2 = v3.lon - v2.lon,
552
- // x1x3 = v1.lon - v3.lon,
553
- // y1y3 = v1.lat - v3.lat,
554
- // y3y1 = v3.lat - v1.lat,
555
- // xx3 = p.lon - v3.lon,
556
- // yy3 = p.lat - v3.lat;
557
-
558
- // const d = y2y3 * x1x3 + x3x2 * y1y3,
559
- // lambda1 = (y2y3 * xx3 + x3x2 * yy3) / d,
560
- // lambda2 = (y3y1 * xx3 + x1x3 * yy3) / d;
561
-
562
- // res[0] = lambda1;
563
- // res[1] = lambda2;
564
- // res[2] = 1 - lambda1 - lambda2;
565
-
566
- // return 0 <= res[0] && res[0] <= 1 && 0 <= lambda1 && lambda1 <= 1 && 0 <= lambda2 && lambda2 <= 1;
567
- //};
568
-
569
- /**
570
- * Callback throttling
571
- * @param {any} func
572
- * @param {Number} limit
573
- * @param {Number} skip
574
- */
575
- export function throttle(func, limit, skip) {
576
- let lastFunc;
577
- let lastRan;
578
- return function () {
579
- const context = this;
580
- const args = arguments;
581
- if (!lastRan) {
582
- func.apply(context, args);
583
- lastRan = Date.now();
584
- } else {
585
- if (skip) {
586
- clearTimeout(lastFunc);
587
- }
588
- lastFunc = setTimeout(function () {
589
- if (Date.now() - lastRan >= limit) {
590
- func.apply(context, args);
591
- lastRan = Date.now();
592
- }
593
- }, limit - (Date.now() - lastRan));
594
- }
595
- };
596
- }
597
-
598
- /**
599
- *
600
- * y2-----Q12--------------Q22---
601
- * | | | |
602
- * | | | |
603
- * y-------|-----P----------|----
604
- * | | | |
605
- * | | | |
606
- * | | | |
607
- * | | | |
608
- * | | | |
609
- * y1-----Q11----|---------Q21---
610
- * | | |
611
- * | | |
612
- * x1 x x2
613
- *
614
- *
615
- * @param {Number} x -
616
- * @param {Number} y -
617
- * @param {Number} fQ11 -
618
- * @param {Number} fQ21 -
619
- * @param {Number} fQ12 -
620
- * @param {Number} fQ22 -
621
- * @param {Number} [x1=0.0] -
622
- * @param {Number} [x2=1.0] -
623
- * @param {Number} [y1=0.0] -
624
- * @param {Number} [y2=1.0] -
625
- */
626
- export function blerp(x, y, fQ11, fQ21, fQ12, fQ22, x1 = 0.0, x2 = 1.0, y1 = 0.0, y2 = 1.0) {
627
- return (
628
- (fQ11 * (x2 - x) * (y2 - y) +
629
- fQ21 * (x - x1) * (y2 - y) +
630
- fQ12 * (x2 - x) * (y - y1) +
631
- fQ22 * (x - x1) * (y - y1)) /
632
- ((x2 - x1) * (y2 - y1))
633
- );
634
- }
635
-
636
- export function blerp2(x, y, fQ11, fQ21, fQ12, fQ22) {
637
- return (
638
- fQ11 * (1.0 - x) * (1.0 - y) + fQ21 * x * (1.0 - y) + fQ12 * (1.0 - x) * y + fQ22 * x * y
639
- );
640
- }
641
-
642
- export function extractElevationTiles(rgbaData, outCurrenElevations, outChildrenElevations) {
643
- let destSize = Math.sqrt(outCurrenElevations.length) - 1;
644
- let destSizeOne = destSize + 1;
645
- let sourceSize = Math.sqrt(rgbaData.length / 4);
646
- let dt = sourceSize / destSize;
647
-
648
- let rightHeigh = 0,
649
- bottomHeigh = 0;
650
-
651
- for (
652
- let k = 0, currIndex = 0, sourceDataLength = rgbaData.length / 4;
653
- k < sourceDataLength;
654
- k++
655
- ) {
656
- let height = rgbaData[k * 4];
657
-
658
- let i = Math.floor(k / sourceSize),
659
- j = k % sourceSize;
660
-
661
- let tileX = Math.floor(j / destSize),
662
- tileY = Math.floor(i / destSize);
663
-
664
- let destArr = outChildrenElevations[tileY][tileX];
665
-
666
- let ii = i % destSize,
667
- jj = j % destSize;
668
-
669
- let destIndex = (ii + tileY) * destSizeOne + jj + tileX;
670
-
671
- destArr[destIndex] = height;
672
-
673
- if ((i + tileY) % dt === 0 && (j + tileX) % dt === 0) {
674
- outCurrenElevations[currIndex++] = height;
675
- }
676
-
677
- if ((j + 1) % destSize === 0 && j !== sourceSize - 1) {
678
- //current tile
679
- rightHeigh = rgbaData[(k + 1) * 4];
680
- let middleHeight = (height + rightHeigh) * 0.5;
681
- destIndex = (ii + tileY) * destSizeOne + jj + 1;
682
- destArr[destIndex] = middleHeight;
683
-
684
- if ((i + tileY) % dt === 0) {
685
- outCurrenElevations[currIndex++] = middleHeight;
686
- }
687
-
688
- //next right tile
689
- let rightindex = (ii + tileY) * destSizeOne + ((jj + 1) % destSize);
690
- outChildrenElevations[tileY][tileX + 1][rightindex] = middleHeight;
691
- }
692
-
693
- if ((i + 1) % destSize === 0 && i !== sourceSize - 1) {
694
- //current tile
695
- bottomHeigh = rgbaData[(k + sourceSize) * 4];
696
- let middleHeight = (height + bottomHeigh) * 0.5;
697
- destIndex = (ii + 1) * destSizeOne + jj + tileX;
698
- destArr[destIndex] = middleHeight;
699
-
700
- if ((j + tileX) % dt === 0) {
701
- outCurrenElevations[currIndex++] = middleHeight;
702
- }
703
-
704
- //next bottom tile
705
- let bottomindex = ((ii + 1) % destSize) * destSizeOne + jj + tileX;
706
- outChildrenElevations[tileY + 1][tileX][bottomindex] = middleHeight;
707
- }
708
-
709
- if (
710
- (j + 1) % destSize === 0 &&
711
- j !== sourceSize - 1 &&
712
- (i + 1) % destSize === 0 &&
713
- i !== sourceSize - 1
714
- ) {
715
- //current tile
716
- let rightBottomHeight = rgbaData[(k + sourceSize + 1) * 4];
717
- let middleHeight = (height + rightHeigh + bottomHeigh + rightBottomHeight) * 0.25;
718
- destIndex = (ii + 1) * destSizeOne + (jj + 1);
719
- destArr[destIndex] = middleHeight;
720
-
721
- outCurrenElevations[currIndex++] = middleHeight;
722
-
723
- //next right tile
724
- let rightindex = (ii + 1) * destSizeOne;
725
- outChildrenElevations[tileY][tileX + 1][rightindex] = middleHeight;
726
-
727
- //next bottom tile
728
- let bottomindex = destSize;
729
- outChildrenElevations[tileY + 1][tileX][bottomindex] = middleHeight;
730
-
731
- //next right bottom tile
732
- let rightBottomindex = 0;
733
- outChildrenElevations[tileY + 1][tileX + 1][rightBottomindex] = middleHeight;
734
- }
735
- }
736
- }
737
-
738
- /**
739
- * Concatenates two the same type arrays
740
- * @param {TypedArray} a
741
- * @param {TypedArray} b
742
- */
743
- export function concatTypedArrays(a, b) {
744
- var c = new a.constructor(a.length + b.length);
745
- c.set(a, 0);
746
- c.set(b, a.length);
747
- return c;
748
- }
749
-
750
- /**
751
- * Concatenates two the same arrays
752
- * @param {TypedArray | Array} a
753
- * @param {TypedArray | Array} b
754
- */
755
- export function concatArrays(a = [], b) {
756
- if (ArrayBuffer.isView(a)) {
757
- return concatTypedArrays(a, b);
758
- } else {
759
- for (var i = 0; i < b.length; i++) {
760
- a.push(b[i]);
761
- }
762
- return a;
763
- }
764
- }
765
-
766
- /**
767
- * Convert simple array to typed
768
- * @param arr {Array}
769
- * @param ctor {Float32ArrayConstructor}
770
- * @returns {TypedArray}
771
- */
772
- export function makeArrayTyped(arr, ctor = Float32Array) {
773
- if (!ArrayBuffer.isView(arr)) {
774
- const typedArr = new ctor(arr.length);
775
- typedArr.set(arr, 0);
776
- return typedArr;
777
- } else {
778
- return arr;
779
- }
780
- }
781
-
782
- /**
783
- * Convert typed array to array
784
- * @param arr {TypedArray}
785
- * @returns {Array}
786
- */
787
- export function makeArray(arr) {
788
- if (ArrayBuffer.isView(arr)) {
789
- return Array.from(arr);
790
- } else {
791
- return arr;
792
- }
793
- }
794
-
795
- /**
796
- *
797
- * @param {TypedArray | Array} arr
798
- * @param {Number} starting
799
- * @param {Number} deleteCount
800
- * @param {Array} elements
801
- */
802
-
803
- export function spliceArray(arr, starting, deleteCount, elements) {
804
- if (ArrayBuffer.isView(arr)) {
805
- return spliceTypedArray(arr, starting, deleteCount, elements);
806
- } else {
807
- arr.splice(starting, deleteCount);
808
- return arr;
809
- }
810
- }
811
-
812
- /**
813
- *
814
- * @param {TypedArray} arr
815
- * @param {Number} starting
816
- * @param {Number} deleteCount
817
- * @param {Array} elements
818
- */
819
- export function spliceTypedArray(arr, starting, deleteCount, elements = []) {
820
- if (arr.length === 0) {
821
- return arr;
822
- }
823
- const newSize = arr.length - deleteCount + elements.length;
824
- const splicedArray = new arr.constructor(newSize);
825
- splicedArray.set(arr.subarray(0, starting));
826
- splicedArray.set(elements, starting);
827
- splicedArray.set(arr.subarray(starting + deleteCount), starting + elements.length);
828
- return splicedArray;
829
- }
830
-
831
- /**
832
- * Returns triangle coordinate array from inside of the source triangle array.
833
- * @static
834
- * @param {Array.<number>} sourceArr - Source array
835
- * @param {number} gridSize - Source array square matrix size
836
- * @param {number} i0 - First row index source array matrix
837
- * @param {number} j0 - First column index
838
- * @param {number} size - Square matrix result size.
839
- * @return{Array.<number>} Triangle coordinates array from the source array.
840
- * @TODO: optimization
841
- */
842
- export function getMatrixSubArray(sourceArr, gridSize, i0, j0, size) {
843
- const size_1 = size + 1;
844
- const i0size = i0 + size_1;
845
- const j0size = j0 + size_1;
846
-
847
- var res = new Float64Array(size_1 * size_1 * 3);
848
-
849
- var vInd = 0;
850
- for (var i = i0; i < i0size; i++) {
851
- for (var j = j0; j < j0size; j++) {
852
- var ind = 3 * (i * (gridSize + 1) + j);
853
-
854
- res[vInd++] = sourceArr[ind];
855
- res[vInd++] = sourceArr[ind + 1];
856
- res[vInd++] = sourceArr[ind + 2];
857
- }
858
- }
859
- return res;
860
- }
861
-
862
- /**
863
- * Returns two float32 triangle coordinate arrays from inside of the source triangle array.
864
- * @static
865
- * @param {Array.<number>} sourceArr - Source array
866
- * @param {number} gridSize - Source array square matrix size
867
- * @param {number} i0 - First row index source array matrix
868
- * @param {number} j0 - First column index
869
- * @param {number} size - Square matrix result size.
870
- * @param {object} outBounds - Output bounds.
871
- * @return{Array.<number>} Triangle coordinates array from the source array.
872
- * @TODO: optimization
873
- */
874
- export function getMatrixSubArrayBoundsExt(
875
- sourceArr,
876
- sourceArrHigh,
877
- sourceArrLow,
878
- noDataVertices,
879
- gridSize,
880
- i0,
881
- j0,
882
- size,
883
- outArr,
884
- outArrHigh,
885
- outArrLow,
886
- outBounds,
887
- outNoDataVertices
888
- ) {
889
- const i0size = i0 + size + 1;
890
- const j0size = j0 + size + 1;
891
- gridSize += 1;
892
- var vInd = 0,
893
- nInd = 0;
894
- for (var i = i0; i < i0size; i++) {
895
- for (var j = j0; j < j0size; j++) {
896
- let indBy3 = i * gridSize + j,
897
- ind = 3 * indBy3;
898
-
899
- let x = sourceArr[ind],
900
- y = sourceArr[ind + 1],
901
- z = sourceArr[ind + 2];
902
-
903
- if (!noDataVertices || noDataVertices[indBy3] === 0) {
904
- if (x < outBounds.xmin) outBounds.xmin = x;
905
- if (x > outBounds.xmax) outBounds.xmax = x;
906
- if (y < outBounds.ymin) outBounds.ymin = y;
907
- if (y > outBounds.ymax) outBounds.ymax = y;
908
- if (z < outBounds.zmin) outBounds.zmin = z;
909
- if (z > outBounds.zmax) outBounds.zmax = z;
910
- } else {
911
- outNoDataVertices[nInd] = 1;
912
- }
913
-
914
- nInd++;
915
-
916
- outArr[vInd] = x;
917
- outArrLow[vInd] = sourceArrLow[ind];
918
- outArrHigh[vInd++] = sourceArrHigh[ind];
919
-
920
- outArr[vInd] = y;
921
- outArrLow[vInd] = sourceArrLow[ind + 1];
922
- outArrHigh[vInd++] = sourceArrHigh[ind + 1];
923
-
924
- outArr[vInd] = z;
925
- outArrLow[vInd] = sourceArrLow[ind + 2];
926
- outArrHigh[vInd++] = sourceArrHigh[ind + 2];
927
- }
928
- }
929
- }
930
-
931
- export function cloneArray(items) {
932
- return items.map((item) => (Array.isArray(item) ? cloneArray(item) : item));
933
- }
934
-
935
- /**
936
- * Returns true if the object pointer is undefined.
937
- * @function
938
- * @param {Object} obj - Object pointer.
939
- * @returns {boolean} Returns true if object is undefined.
940
- */
941
- export function isUndef(obj) {
942
- return obj === void 0;
1
+ /**
2
+ * @module og/utils/shared
3
+ */
4
+
5
+ "use strict";
6
+
7
+ import { ajax } from "../ajax.js";
8
+ import { colorTable } from "./colorTable.js";
9
+ import { Extent } from "../Extent.js";
10
+ import { LonLat } from "../LonLat.js";
11
+ import { Vec2 } from "../math/Vec2.js";
12
+ import { Vec3 } from "../math/Vec3.js";
13
+ import { Vec4 } from "../math/Vec4.js";
14
+
15
+ export function getDefault(param, def) {
16
+ return param != undefined ? param : def;
17
+ }
18
+
19
+ export function isEmpty(v) {
20
+ return v == null;
21
+ }
22
+
23
+ let _stampCounter = 0;
24
+
25
+ export function stamp(obj) {
26
+ var stamp = obj._openglobus_id;
27
+ if (!stamp) {
28
+ stamp = obj._openglobus_id = ++_stampCounter;
29
+ }
30
+ return stamp;
31
+ }
32
+
33
+ export function isString(s) {
34
+ return typeof s === "string" || s instanceof String;
35
+ }
36
+
37
+ /**
38
+ * Synchronous text file loading. Returns file text.
39
+ * @param {string} fileUrl - File name path.
40
+ * @returns {string} -
41
+ */
42
+ export function readTextFile(fileUrl) {
43
+ var res = "";
44
+
45
+ ajax.request(fileUrl, {
46
+ async: false,
47
+ success: function (data) {
48
+ res = data;
49
+ }
50
+ });
51
+
52
+ return res;
53
+ }
54
+
55
+ /**
56
+ * Convert html color string to the RGBA number vector.
57
+ * @param {string} htmlColor - HTML string("#C6C6C6" or "#EF5" or "rgb(8,8,8)" or "rgba(8,8,8)") color.
58
+ * @param {number} [opacity] - Opacity for the output vector.
59
+ * @returns {math.Vec4} -
60
+ */
61
+ export function htmlColorToRgba(htmlColor, opacity) {
62
+ var hColor = colorTable[htmlColor];
63
+ if (hColor) {
64
+ htmlColor = hColor;
65
+ }
66
+
67
+ if (htmlColor[0] === "#") {
68
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
69
+ var hex = htmlColor.replace(shorthandRegex, function (m, r, g, b) {
70
+ return r + r + g + g + b + b;
71
+ });
72
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
73
+ return new Vec4(
74
+ parseInt(result[1], 16) / 255,
75
+ parseInt(result[2], 16) / 255,
76
+ parseInt(result[3], 16) / 255,
77
+ isEmpty(opacity) ? 1.0 : opacity
78
+ );
79
+ } else {
80
+ if (isEmpty(opacity)) {
81
+ opacity = 1.0;
82
+ }
83
+ var m = htmlColor.split(",");
84
+ return new Vec4(
85
+ parseInt(m[0].split("(")[1]) / 255,
86
+ parseInt(m[1]) / 255,
87
+ parseInt(m[2]) / 255,
88
+ !isEmpty(m[3]) ? parseFloat(m[3]) : opacity
89
+ );
90
+ }
91
+ }
92
+
93
+ export function htmlColorToFloat32Array(htmlColor, opacity) {
94
+ let c = htmlColorToRgba(htmlColor, opacity);
95
+ return new Float32Array([c.x, c.y, c.z, c.w]);
96
+ }
97
+
98
+ /**
99
+ * Convert html color string to the RGB number vector.
100
+ * @param {string} htmlColor - HTML string("#C6C6C6" or "#EF5" or "rgb(8,8,8)" or "rgba(8,8,8)") color.
101
+ * @param {number} [opacity] - Opacity for the output vector.
102
+ * @returns {Vec3} -
103
+ */
104
+ export function htmlColorToRgb(htmlColor) {
105
+ var hColor = colorTable[htmlColor];
106
+ if (hColor) {
107
+ htmlColor = hColor;
108
+ }
109
+
110
+ if (htmlColor[0] === "#") {
111
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
112
+ var hex = htmlColor.replace(shorthandRegex, function (m, r, g, b) {
113
+ return r + r + g + g + b + b;
114
+ });
115
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
116
+ return new Vec3(
117
+ parseInt(result[1], 16) / 255,
118
+ parseInt(result[2], 16) / 255,
119
+ parseInt(result[3], 16) / 255
120
+ );
121
+ } else {
122
+ var m = htmlColor.split(",");
123
+ return new Vec3(
124
+ parseInt(m[0].split("(")[1]) / 255,
125
+ parseInt(m[1]) / 255,
126
+ parseInt(m[2]) / 255
127
+ );
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Replace template substrings between '{' and '}' tokens.
133
+ * @param {string} template - String with templates in "{" and "}"
134
+ * @param {Object} params - Template named object with subsrtings.
135
+ * @returns {string} -
136
+ *
137
+ * @example <caption>Example from og.terrain that replaces tile indexes in url:</caption>
138
+ * var substrings = {
139
+ * "x": 12,
140
+ * "y": 15,
141
+ * "z": 8
142
+ * }
143
+ * og.utils.stringTemplate("http://earth3.openglobus.org/{z}/{y}/{x}.ddm", substrins);
144
+ * //returns http://earth3.openglobus.org/8/15/12.ddm
145
+ */
146
+ export function stringTemplate(template, params) {
147
+ return template.replace(/{[^{}]+}/g, function (key) {
148
+ return params[key.replace(/[{}]+/g, "")] || "";
149
+ });
150
+ }
151
+
152
+ export function getHTML(template, params) {
153
+ return stringTemplate(template, params);
154
+ }
155
+
156
+ export function parseHTML(htmlStr) {
157
+ var p = document.createElement("div");
158
+ p.innerHTML = htmlStr;
159
+ var domArr = [];
160
+ for (var i = 0; i < p.childNodes.length; i++) {
161
+ domArr.push(p.childNodes[i]);
162
+ p.removeChild(p.childNodes[i]);
163
+ }
164
+ return domArr;
165
+ }
166
+
167
+ export function print2d(id, text, x, y) {
168
+ var el = document.getElementById(id);
169
+ if (!el) {
170
+ el = document.createElement("div");
171
+ el.id = id;
172
+ el.classList.add("defaultText");
173
+ document.body.appendChild(el);
174
+ }
175
+ el.innerHTML = text;
176
+ el.style.left = x;
177
+ el.style.top = y;
178
+ }
179
+
180
+ export function defaultString(str, def) {
181
+ return str ? str.trim().toLowerCase() : def;
182
+ }
183
+
184
+ export function createVector3(v, def) {
185
+ if (v) {
186
+ if (v instanceof Vec3) {
187
+ return v.clone();
188
+ } else if (v instanceof Array) {
189
+ return Vec3.fromVec(v);
190
+ }
191
+ } else if (def) {
192
+ return def;
193
+ }
194
+ return new Vec3();
195
+ }
196
+
197
+ export function createVector4(v, def) {
198
+ if (v) {
199
+ if (v instanceof Vec4) {
200
+ return v.clone();
201
+ } else if (v instanceof Array) {
202
+ return Vec4.fromVec(v);
203
+ }
204
+ } else if (def) {
205
+ return def;
206
+ }
207
+ return new Vec4();
208
+ }
209
+
210
+ export function createColorRGBA(c, def) {
211
+ if (c) {
212
+ if (isString(c)) {
213
+ return htmlColorToRgba(c);
214
+ } else if (c instanceof Array) {
215
+ return Vec4.fromVec(c);
216
+ } else if (c instanceof Vec4) {
217
+ return c.clone();
218
+ }
219
+ } else if (def) {
220
+ return def;
221
+ }
222
+ return new Vec4(1.0, 1.0, 1.0, 1.0);
223
+ }
224
+
225
+ export function createColorRGB(c, def) {
226
+ if (c) {
227
+ if (isString(c)) {
228
+ return htmlColorToRgb(c);
229
+ } else if (c instanceof Array) {
230
+ return Vec3.fromVec(c);
231
+ } else if (c instanceof Vec3) {
232
+ return c.clone();
233
+ }
234
+ } else if (def) {
235
+ return def;
236
+ }
237
+ return new Vec3(1.0, 1.0, 1.0);
238
+ }
239
+
240
+ export function createExtent(e, def) {
241
+ if (e) {
242
+ if (e instanceof Array) {
243
+ return new Extent(createLonLat(e[0]), createLonLat(e[1]));
244
+ } else if (e instanceof Extent) {
245
+ return e.clone();
246
+ }
247
+ } else if (def) {
248
+ return def;
249
+ }
250
+ return new Extent();
251
+ }
252
+
253
+ export function createLonLat(l, def = null) {
254
+ if (l) {
255
+ if (l instanceof Array) {
256
+ return new LonLat(l[0], l[1], l[2]);
257
+ } else if (l instanceof LonLat) {
258
+ return l.clone();
259
+ }
260
+ } else if (def) {
261
+ return def;
262
+ }
263
+ return new LonLat();
264
+ }
265
+
266
+ export function binarySearchFast(arr, x) {
267
+ let start = 0,
268
+ end = arr.length - 1;
269
+ while (start <= end) {
270
+ let k = Math.floor((start + end) * 0.5);
271
+ if (arr[k] === x) {
272
+ return k;
273
+ } else if (arr[k] < x) {
274
+ start = k + 1;
275
+ } else {
276
+ end = k - 1;
277
+ }
278
+ }
279
+ return -1;
280
+ }
281
+
282
+ /**
283
+ * Finds an item in a sorted array.
284
+ * @param {Array} ar The sorted array to search.
285
+ * @param {Object} el The item to find in the array.
286
+ * @param {utils.binarySearch~compare_fn} compare_fn comparator The function to use to compare the item to
287
+ * elements in the array.
288
+ * @returns {Number} a negative number if a is less than b; 0 if a is equal to b;a positive number of a is greater than b.
289
+ *
290
+ * @example
291
+ * // Create a comparator function to search through an array of numbers.
292
+ * function comparator(a, b) {
293
+ * return a - b;
294
+ * };
295
+ * var numbers = [0, 2, 4, 6, 8];
296
+ * var index = og.utils.binarySearch(numbers, 6, comparator); // 3
297
+ */
298
+ export function binarySearch(ar, el, compare_fn) {
299
+ var m = 0;
300
+ var n = ar.length - 1;
301
+ while (m <= n) {
302
+ var k = (n + m) >> 1;
303
+ var cmp = compare_fn(el, ar[k], k);
304
+ if (cmp > 0) {
305
+ m = k + 1;
306
+ } else if (cmp < 0) {
307
+ n = k - 1;
308
+ } else {
309
+ return k;
310
+ }
311
+ }
312
+ return -m - 1;
313
+ }
314
+
315
+ /**
316
+ * Binary insertion that uses binarySearch algorithm.
317
+ * @param {Array} ar - The sorted array to insert.
318
+ * @param {Object} el - The item to insert.
319
+ * @param {utils.binarySearch~compare_fn} compare_fn - comparator The function to use to compare the item to
320
+ * elements in the array.
321
+ * @returns {Number} Array index position in which item inserted in.
322
+ */
323
+ export function binaryInsert(ar, el, compare_fn) {
324
+ var i = binarySearch(ar, el, compare_fn);
325
+ if (i < 0) {
326
+ i = ~i;
327
+ }
328
+ ar.splice(i, 0, el);
329
+ return i;
330
+ }
331
+
332
+ /**
333
+ * Returns two segment lines intersection coordinate.
334
+ * @static
335
+ * @param {math.Vec2} start1 - First line first coordinate.
336
+ * @param {math.Vec2} end1 - First line second coordinate.
337
+ * @param {math.Vec2} start2 - Second line first coordinate.
338
+ * @param {math.Vec2} end2 - Second line second coordinate.
339
+ * @param {boolean} [isSegment] - Lines are segments.
340
+ * @return {math.Vec2} - Intersection coordinate.
341
+ */
342
+ export function getLinesIntersection2v(start1, end1, start2, end2, isSegment) {
343
+ var dir1 = end1.sub(start1);
344
+ var dir2 = end2.sub(start2);
345
+
346
+ var a1 = -dir1.y;
347
+ var b1 = +dir1.x;
348
+ var d1 = -(a1 * start1.x + b1 * start1.y);
349
+
350
+ var a2 = -dir2.y;
351
+ var b2 = +dir2.x;
352
+ var d2 = -(a2 * start2.x + b2 * start2.y);
353
+
354
+ var seg1_line2_start = a2 * start1.x + b2 * start1.y + d2;
355
+ var seg1_line2_end = a2 * end1.x + b2 * end1.y + d2;
356
+
357
+ var seg2_line1_start = a1 * start2.x + b1 * start2.y + d1;
358
+ var seg2_line1_end = a1 * end2.x + b1 * end2.y + d1;
359
+
360
+ if (
361
+ isSegment &&
362
+ (seg1_line2_start * seg1_line2_end > 0 || seg2_line1_start * seg2_line1_end > 0)
363
+ ) {
364
+ return null;
365
+ }
366
+
367
+ var u = seg1_line2_start / (seg1_line2_start - seg1_line2_end);
368
+
369
+ return new Vec2(start1.x + u * dir1.x, start1.y + u * dir1.y);
370
+ }
371
+
372
+ /**
373
+ * Returns two segment lines intersection coordinate.
374
+ * @static
375
+ * @param {math.Vec2} start1 - First line first coordinate.
376
+ * @param {math.Vec2} end1 - First line second coordinate.
377
+ * @param {math.Vec2} start2 - Second line first coordinate.
378
+ * @param {math.Vec2} end2 - Second line second coordinate.
379
+ * @param {boolean} [isSegment] - Lines are segments.
380
+ * @return {math.Vec2} - Intersection coordinate.
381
+ */
382
+ export function getLinesIntersectionLonLat(start1, end1, start2, end2, isSegment) {
383
+ var dir1 = new LonLat(end1.lon - start1.lon, end1.lat - start1.lat);
384
+ var dir2 = new LonLat(end2.lon - start2.lon, end2.lat - start2.lat);
385
+
386
+ var a1 = -dir1.lat;
387
+ var b1 = +dir1.lon;
388
+ var d1 = -(a1 * start1.lon + b1 * start1.lat);
389
+
390
+ var a2 = -dir2.lat;
391
+ var b2 = +dir2.lon;
392
+ var d2 = -(a2 * start2.lon + b2 * start2.lat);
393
+
394
+ var seg1_line2_start = a2 * start1.lon + b2 * start1.lat + d2;
395
+ var seg1_line2_end = a2 * end1.lon + b2 * end1.lat + d2;
396
+
397
+ var seg2_line1_start = a1 * start2.lon + b1 * start2.lat + d1;
398
+ var seg2_line1_end = a1 * end2.lon + b1 * end2.lat + d1;
399
+
400
+ if (
401
+ isSegment &&
402
+ (seg1_line2_start * seg1_line2_end > 0 || seg2_line1_start * seg2_line1_end > 0)
403
+ ) {
404
+ return null;
405
+ }
406
+
407
+ var u = seg1_line2_start / (seg1_line2_start - seg1_line2_end);
408
+
409
+ return new LonLat(start1.lon + u * dir1.lon, start1.lat + u * dir1.lat);
410
+ }
411
+
412
+ /**
413
+ * Converts XML to JSON
414
+ * @static
415
+ * @param {Object} xml - Xml object
416
+ * @return {Object} - Json converted object.
417
+ */
418
+ export function xmlToJson(xml) {
419
+ // Create the return object
420
+ var obj = {};
421
+
422
+ if (xml.nodeType === 1) {
423
+ // element
424
+ // do attributes
425
+ if (xml.attributes.length > 0) {
426
+ obj["@attributes"] = {};
427
+ for (var j = 0; j < xml.attributes.length; j++) {
428
+ var attribute = xml.attributes.item(j);
429
+ obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
430
+ }
431
+ }
432
+ } else if (xml.nodeType === 3) {
433
+ // text
434
+ obj = xml.nodeValue;
435
+ }
436
+
437
+ // do children
438
+ if (xml.hasChildNodes()) {
439
+ for (var i = 0; i < xml.childNodes.length; i++) {
440
+ var item = xml.childNodes.item(i);
441
+ var nodeName = item.nodeName;
442
+ if (typeof obj[nodeName] === "undefined") {
443
+ obj[nodeName] = xmlToJson(item);
444
+ } else {
445
+ if (typeof obj[nodeName].push === "undefined") {
446
+ var old = obj[nodeName];
447
+ obj[nodeName] = [];
448
+ obj[nodeName].push(old);
449
+ }
450
+ obj[nodeName].push(xmlToJson(item));
451
+ }
452
+ }
453
+ }
454
+ return obj;
455
+ }
456
+
457
+ export const castType = {
458
+ string: function (v) {
459
+ return isEmpty(v) ? v : v.toString();
460
+ },
461
+
462
+ date: function (v) {
463
+ return isEmpty(v) ? v : new Date(v * 1000);
464
+ },
465
+
466
+ datetime: function (v) {
467
+ return isEmpty(v) ? v : new Date(v * 1000);
468
+ },
469
+
470
+ time: function (v) {
471
+ return isEmpty(v) ? v : parseInt(v);
472
+ },
473
+
474
+ integer: function (v) {
475
+ return isEmpty(v) ? v : parseInt(v);
476
+ },
477
+
478
+ float: function (v) {
479
+ return isEmpty(v) ? v : parseFloat(v);
480
+ },
481
+
482
+ boolean: function (str) {
483
+ if (str === null) {
484
+ return str;
485
+ }
486
+
487
+ if (typeof str === "boolean") {
488
+ if (str === true) {
489
+ return true;
490
+ }
491
+ return false;
492
+ }
493
+ if (typeof str === "string") {
494
+ if (str === "") {
495
+ return false;
496
+ }
497
+ str = str.replace(/^\s+|\s+$/g, "");
498
+ if (str.toLowerCase() === "true" || str.toLowerCase() === "yes") {
499
+ return true;
500
+ }
501
+ str = str.replace(/,/g, ".");
502
+ str = str.replace(/^\s*\-\s*/g, "-");
503
+ }
504
+ if (!isNaN(str)) {
505
+ return parseFloat(str) !== 0;
506
+ }
507
+ return false;
508
+ }
509
+ };
510
+
511
+ export function base64toBlob(base64Data, contentType) {
512
+ contentType = contentType || "";
513
+ var sliceSize = 1024;
514
+ var byteCharacters = atob(base64Data);
515
+ var bytesLength = byteCharacters.length;
516
+ var slicesCount = Math.ceil(bytesLength / sliceSize);
517
+ var byteArrays = new Array(slicesCount);
518
+
519
+ for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
520
+ var begin = sliceIndex * sliceSize;
521
+ var end = Math.min(begin + sliceSize, bytesLength);
522
+
523
+ var bytes = new Array(end - begin);
524
+ for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
525
+ bytes[i] = byteCharacters[offset].charCodeAt(0);
526
+ }
527
+ byteArrays[sliceIndex] = new Uint8Array(bytes);
528
+ }
529
+ return new Blob(byteArrays, { type: contentType });
530
+ }
531
+
532
+ export function base64StringToBlog(string) {
533
+ let block = string.split(";");
534
+ let contentType = block[0].split(":")[1];
535
+ let data = block[1].split(",")[1];
536
+
537
+ return base64toBlob(data, contentType);
538
+ }
539
+
540
+ ///**
541
+ // *
542
+ // * @param {LonLat} p
543
+ // * @param {LonLat} v1
544
+ // * @param {LonLat} v2
545
+ // * @param {LonLat} v3
546
+ // * @param {Array<Number>} res
547
+ // */
548
+ //export function cartesianToBarycentricLonLat(p, v1, v2, v3, res) {
549
+
550
+ // const y2y3 = v2.lat - v3.lat,
551
+ // x3x2 = v3.lon - v2.lon,
552
+ // x1x3 = v1.lon - v3.lon,
553
+ // y1y3 = v1.lat - v3.lat,
554
+ // y3y1 = v3.lat - v1.lat,
555
+ // xx3 = p.lon - v3.lon,
556
+ // yy3 = p.lat - v3.lat;
557
+
558
+ // const d = y2y3 * x1x3 + x3x2 * y1y3,
559
+ // lambda1 = (y2y3 * xx3 + x3x2 * yy3) / d,
560
+ // lambda2 = (y3y1 * xx3 + x1x3 * yy3) / d;
561
+
562
+ // res[0] = lambda1;
563
+ // res[1] = lambda2;
564
+ // res[2] = 1 - lambda1 - lambda2;
565
+
566
+ // return 0 <= res[0] && res[0] <= 1 && 0 <= lambda1 && lambda1 <= 1 && 0 <= lambda2 && lambda2 <= 1;
567
+ //};
568
+
569
+ /**
570
+ * Callback throttling
571
+ * @param {any} func
572
+ * @param {Number} limit
573
+ * @param {Number} skip
574
+ */
575
+ export function throttle(func, limit, skip) {
576
+ let lastFunc;
577
+ let lastRan;
578
+ return function () {
579
+ const context = this;
580
+ const args = arguments;
581
+ if (!lastRan) {
582
+ func.apply(context, args);
583
+ lastRan = Date.now();
584
+ } else {
585
+ if (skip) {
586
+ clearTimeout(lastFunc);
587
+ }
588
+ lastFunc = setTimeout(function () {
589
+ if (Date.now() - lastRan >= limit) {
590
+ func.apply(context, args);
591
+ lastRan = Date.now();
592
+ }
593
+ }, limit - (Date.now() - lastRan));
594
+ }
595
+ };
596
+ }
597
+
598
+ /**
599
+ *
600
+ * y2-----Q12--------------Q22---
601
+ * | | | |
602
+ * | | | |
603
+ * y-------|-----P----------|----
604
+ * | | | |
605
+ * | | | |
606
+ * | | | |
607
+ * | | | |
608
+ * | | | |
609
+ * y1-----Q11----|---------Q21---
610
+ * | | |
611
+ * | | |
612
+ * x1 x x2
613
+ *
614
+ *
615
+ * @param {Number} x -
616
+ * @param {Number} y -
617
+ * @param {Number} fQ11 -
618
+ * @param {Number} fQ21 -
619
+ * @param {Number} fQ12 -
620
+ * @param {Number} fQ22 -
621
+ * @param {Number} [x1=0.0] -
622
+ * @param {Number} [x2=1.0] -
623
+ * @param {Number} [y1=0.0] -
624
+ * @param {Number} [y2=1.0] -
625
+ */
626
+ export function blerp(x, y, fQ11, fQ21, fQ12, fQ22, x1 = 0.0, x2 = 1.0, y1 = 0.0, y2 = 1.0) {
627
+ return (
628
+ (fQ11 * (x2 - x) * (y2 - y) +
629
+ fQ21 * (x - x1) * (y2 - y) +
630
+ fQ12 * (x2 - x) * (y - y1) +
631
+ fQ22 * (x - x1) * (y - y1)) /
632
+ ((x2 - x1) * (y2 - y1))
633
+ );
634
+ }
635
+
636
+ export function blerp2(x, y, fQ11, fQ21, fQ12, fQ22) {
637
+ return (
638
+ fQ11 * (1.0 - x) * (1.0 - y) + fQ21 * x * (1.0 - y) + fQ12 * (1.0 - x) * y + fQ22 * x * y
639
+ );
640
+ }
641
+
642
+ export function extractElevationTiles(rgbaData, outCurrenElevations, outChildrenElevations) {
643
+ let destSize = Math.sqrt(outCurrenElevations.length) - 1;
644
+ let destSizeOne = destSize + 1;
645
+ let sourceSize = Math.sqrt(rgbaData.length / 4);
646
+ let dt = sourceSize / destSize;
647
+
648
+ let rightHeigh = 0,
649
+ bottomHeigh = 0;
650
+
651
+ for (
652
+ let k = 0, currIndex = 0, sourceDataLength = rgbaData.length / 4;
653
+ k < sourceDataLength;
654
+ k++
655
+ ) {
656
+ let height = rgbaData[k * 4];
657
+
658
+ let i = Math.floor(k / sourceSize),
659
+ j = k % sourceSize;
660
+
661
+ let tileX = Math.floor(j / destSize),
662
+ tileY = Math.floor(i / destSize);
663
+
664
+ let destArr = outChildrenElevations[tileY][tileX];
665
+
666
+ let ii = i % destSize,
667
+ jj = j % destSize;
668
+
669
+ let destIndex = (ii + tileY) * destSizeOne + jj + tileX;
670
+
671
+ destArr[destIndex] = height;
672
+
673
+ if ((i + tileY) % dt === 0 && (j + tileX) % dt === 0) {
674
+ outCurrenElevations[currIndex++] = height;
675
+ }
676
+
677
+ if ((j + 1) % destSize === 0 && j !== sourceSize - 1) {
678
+ //current tile
679
+ rightHeigh = rgbaData[(k + 1) * 4];
680
+ let middleHeight = (height + rightHeigh) * 0.5;
681
+ destIndex = (ii + tileY) * destSizeOne + jj + 1;
682
+ destArr[destIndex] = middleHeight;
683
+
684
+ if ((i + tileY) % dt === 0) {
685
+ outCurrenElevations[currIndex++] = middleHeight;
686
+ }
687
+
688
+ //next right tile
689
+ let rightindex = (ii + tileY) * destSizeOne + ((jj + 1) % destSize);
690
+ outChildrenElevations[tileY][tileX + 1][rightindex] = middleHeight;
691
+ }
692
+
693
+ if ((i + 1) % destSize === 0 && i !== sourceSize - 1) {
694
+ //current tile
695
+ bottomHeigh = rgbaData[(k + sourceSize) * 4];
696
+ let middleHeight = (height + bottomHeigh) * 0.5;
697
+ destIndex = (ii + 1) * destSizeOne + jj + tileX;
698
+ destArr[destIndex] = middleHeight;
699
+
700
+ if ((j + tileX) % dt === 0) {
701
+ outCurrenElevations[currIndex++] = middleHeight;
702
+ }
703
+
704
+ //next bottom tile
705
+ let bottomindex = ((ii + 1) % destSize) * destSizeOne + jj + tileX;
706
+ outChildrenElevations[tileY + 1][tileX][bottomindex] = middleHeight;
707
+ }
708
+
709
+ if (
710
+ (j + 1) % destSize === 0 &&
711
+ j !== sourceSize - 1 &&
712
+ (i + 1) % destSize === 0 &&
713
+ i !== sourceSize - 1
714
+ ) {
715
+ //current tile
716
+ let rightBottomHeight = rgbaData[(k + sourceSize + 1) * 4];
717
+ let middleHeight = (height + rightHeigh + bottomHeigh + rightBottomHeight) * 0.25;
718
+ destIndex = (ii + 1) * destSizeOne + (jj + 1);
719
+ destArr[destIndex] = middleHeight;
720
+
721
+ outCurrenElevations[currIndex++] = middleHeight;
722
+
723
+ //next right tile
724
+ let rightindex = (ii + 1) * destSizeOne;
725
+ outChildrenElevations[tileY][tileX + 1][rightindex] = middleHeight;
726
+
727
+ //next bottom tile
728
+ let bottomindex = destSize;
729
+ outChildrenElevations[tileY + 1][tileX][bottomindex] = middleHeight;
730
+
731
+ //next right bottom tile
732
+ let rightBottomindex = 0;
733
+ outChildrenElevations[tileY + 1][tileX + 1][rightBottomindex] = middleHeight;
734
+ }
735
+ }
736
+ }
737
+
738
+ /**
739
+ * Concatenates two the same type arrays
740
+ * @param {TypedArray} a
741
+ * @param {TypedArray} b
742
+ */
743
+ export function concatTypedArrays(a, b) {
744
+ var c = new a.constructor(a.length + b.length);
745
+ c.set(a, 0);
746
+ c.set(b, a.length);
747
+ return c;
748
+ }
749
+
750
+ /**
751
+ * Concatenates two the same arrays
752
+ * @param {TypedArray | Array} a
753
+ * @param {TypedArray | Array} b
754
+ */
755
+ export function concatArrays(a = [], b) {
756
+ if (ArrayBuffer.isView(a)) {
757
+ return concatTypedArrays(a, b);
758
+ } else {
759
+ for (var i = 0; i < b.length; i++) {
760
+ a.push(b[i]);
761
+ }
762
+ return a;
763
+ }
764
+ }
765
+
766
+ /**
767
+ * Convert simple array to typed
768
+ * @param arr {Array}
769
+ * @param ctor {Float32ArrayConstructor}
770
+ * @returns {TypedArray}
771
+ */
772
+ export function makeArrayTyped(arr, ctor = Float32Array) {
773
+ if (!ArrayBuffer.isView(arr)) {
774
+ const typedArr = new ctor(arr.length);
775
+ typedArr.set(arr, 0);
776
+ return typedArr;
777
+ } else {
778
+ return arr;
779
+ }
780
+ }
781
+
782
+ /**
783
+ * Convert typed array to array
784
+ * @param arr {TypedArray}
785
+ * @returns {Array}
786
+ */
787
+ export function makeArray(arr) {
788
+ if (ArrayBuffer.isView(arr)) {
789
+ return Array.from(arr);
790
+ } else {
791
+ return arr;
792
+ }
793
+ }
794
+
795
+ /**
796
+ *
797
+ * @param {TypedArray | Array} arr
798
+ * @param {Number} starting
799
+ * @param {Number} deleteCount
800
+ * @param {Array} elements
801
+ */
802
+
803
+ export function spliceArray(arr, starting, deleteCount, elements) {
804
+ if (ArrayBuffer.isView(arr)) {
805
+ return spliceTypedArray(arr, starting, deleteCount, elements);
806
+ } else {
807
+ arr.splice(starting, deleteCount);
808
+ return arr;
809
+ }
810
+ }
811
+
812
+ /**
813
+ *
814
+ * @param {TypedArray} arr
815
+ * @param {Number} starting
816
+ * @param {Number} deleteCount
817
+ * @param {Array} elements
818
+ */
819
+ export function spliceTypedArray(arr, starting, deleteCount, elements = []) {
820
+ if (arr.length === 0) {
821
+ return arr;
822
+ }
823
+ const newSize = arr.length - deleteCount + elements.length;
824
+ const splicedArray = new arr.constructor(newSize);
825
+ splicedArray.set(arr.subarray(0, starting));
826
+ splicedArray.set(elements, starting);
827
+ splicedArray.set(arr.subarray(starting + deleteCount), starting + elements.length);
828
+ return splicedArray;
829
+ }
830
+
831
+ /**
832
+ * Returns triangle coordinate array from inside of the source triangle array.
833
+ * @static
834
+ * @param {Array.<number>} sourceArr - Source array
835
+ * @param {number} gridSize - Source array square matrix size
836
+ * @param {number} i0 - First row index source array matrix
837
+ * @param {number} j0 - First column index
838
+ * @param {number} size - Square matrix result size.
839
+ * @return{Array.<number>} Triangle coordinates array from the source array.
840
+ * @TODO: optimization
841
+ */
842
+ export function getMatrixSubArray(sourceArr, gridSize, i0, j0, size) {
843
+ const size_1 = size + 1;
844
+ const i0size = i0 + size_1;
845
+ const j0size = j0 + size_1;
846
+
847
+ var res = new Float64Array(size_1 * size_1 * 3);
848
+
849
+ var vInd = 0;
850
+ for (var i = i0; i < i0size; i++) {
851
+ for (var j = j0; j < j0size; j++) {
852
+ var ind = 3 * (i * (gridSize + 1) + j);
853
+
854
+ res[vInd++] = sourceArr[ind];
855
+ res[vInd++] = sourceArr[ind + 1];
856
+ res[vInd++] = sourceArr[ind + 2];
857
+ }
858
+ }
859
+ return res;
860
+ }
861
+
862
+ /**
863
+ * Returns two float32 triangle coordinate arrays from inside of the source triangle array.
864
+ * @static
865
+ * @param {Array.<number>} sourceArr - Source array
866
+ * @param {number} gridSize - Source array square matrix size
867
+ * @param {number} i0 - First row index source array matrix
868
+ * @param {number} j0 - First column index
869
+ * @param {number} size - Square matrix result size.
870
+ * @param {object} outBounds - Output bounds.
871
+ * @return{Array.<number>} Triangle coordinates array from the source array.
872
+ * @TODO: optimization
873
+ */
874
+ export function getMatrixSubArrayBoundsExt(
875
+ sourceArr,
876
+ sourceArrHigh,
877
+ sourceArrLow,
878
+ noDataVertices,
879
+ gridSize,
880
+ i0,
881
+ j0,
882
+ size,
883
+ outArr,
884
+ outArrHigh,
885
+ outArrLow,
886
+ outBounds,
887
+ outNoDataVertices
888
+ ) {
889
+ const i0size = i0 + size + 1;
890
+ const j0size = j0 + size + 1;
891
+ gridSize += 1;
892
+ var vInd = 0,
893
+ nInd = 0;
894
+ for (var i = i0; i < i0size; i++) {
895
+ for (var j = j0; j < j0size; j++) {
896
+ let indBy3 = i * gridSize + j,
897
+ ind = 3 * indBy3;
898
+
899
+ let x = sourceArr[ind],
900
+ y = sourceArr[ind + 1],
901
+ z = sourceArr[ind + 2];
902
+
903
+ if (!noDataVertices || noDataVertices[indBy3] === 0) {
904
+ if (x < outBounds.xmin) outBounds.xmin = x;
905
+ if (x > outBounds.xmax) outBounds.xmax = x;
906
+ if (y < outBounds.ymin) outBounds.ymin = y;
907
+ if (y > outBounds.ymax) outBounds.ymax = y;
908
+ if (z < outBounds.zmin) outBounds.zmin = z;
909
+ if (z > outBounds.zmax) outBounds.zmax = z;
910
+ } else {
911
+ outNoDataVertices[nInd] = 1;
912
+ }
913
+
914
+ nInd++;
915
+
916
+ outArr[vInd] = x;
917
+ outArrLow[vInd] = sourceArrLow[ind];
918
+ outArrHigh[vInd++] = sourceArrHigh[ind];
919
+
920
+ outArr[vInd] = y;
921
+ outArrLow[vInd] = sourceArrLow[ind + 1];
922
+ outArrHigh[vInd++] = sourceArrHigh[ind + 1];
923
+
924
+ outArr[vInd] = z;
925
+ outArrLow[vInd] = sourceArrLow[ind + 2];
926
+ outArrHigh[vInd++] = sourceArrHigh[ind + 2];
927
+ }
928
+ }
929
+ }
930
+
931
+ export function cloneArray(items) {
932
+ return items.map((item) => (Array.isArray(item) ? cloneArray(item) : item));
933
+ }
934
+
935
+ /**
936
+ * Returns true if the object pointer is undefined.
937
+ * @function
938
+ * @param {Object} obj - Object pointer.
939
+ * @returns {boolean} Returns true if object is undefined.
940
+ */
941
+ export function isUndef(obj) {
942
+ return obj === void 0;
943
943
  }