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