@eturnity/eturnity_3d 6.34.0 → 6.34.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 (41) hide show
  1. package/.editorconfig +5 -0
  2. package/package.json +8 -4
  3. package/src/App.vue +16 -16
  4. package/src/assets/theme.js +4 -4
  5. package/src/components/ThreeCanvasViewer.vue +56 -43
  6. package/src/config.js +139 -65
  7. package/src/helper/MapView.js +214 -241
  8. package/src/helper/UpdateRoofModuleFieldRelations.js +17 -23
  9. package/src/helper/UpdateRoofObstacleRelations.js +48 -41
  10. package/src/helper/cameraMixin.js +97 -93
  11. package/src/helper/customProvider.js +28 -28
  12. package/src/helper/materialMixin.js +86 -70
  13. package/src/helper/materials.js +64 -49
  14. package/src/helper/render/background.js +2 -5
  15. package/src/helper/render/base.js +43 -40
  16. package/src/helper/render/clear.js +96 -84
  17. package/src/helper/render/edge.js +59 -65
  18. package/src/helper/render/geometryHandler.js +166 -128
  19. package/src/helper/render/imageOverlay.js +157 -106
  20. package/src/helper/render/index.js +21 -3
  21. package/src/helper/render/loader.js +34 -34
  22. package/src/helper/render/mapProjection.js +88 -74
  23. package/src/helper/render/margin.js +46 -50
  24. package/src/helper/render/moduleField.js +26 -24
  25. package/src/helper/render/node.js +43 -43
  26. package/src/helper/render/obstacle.js +50 -48
  27. package/src/helper/render/panel.js +85 -79
  28. package/src/helper/render/projectionMaterial.js +58 -50
  29. package/src/helper/render/roof.js +136 -133
  30. package/src/helper/render/texture.js +17 -17
  31. package/src/helper/render/tile.js +291 -0
  32. package/src/helper/renderMixin.js +30 -37
  33. package/src/helper/threeMixin.js +40 -101
  34. package/src/main.js +22 -18
  35. package/src/store/AddMargin.js +87 -83
  36. package/src/store/hydrateData.js +40 -30
  37. package/src/store/nodesEdgesCreation.js +177 -160
  38. package/src/store/three-d-module.js +41 -27
  39. package/src/utils/cancellablePromise.js +23 -0
  40. package/.eslintrc.json +0 -18
  41. package/src/helper/geo-three.module.js +0 -1903
@@ -1,1903 +0,0 @@
1
- import { Texture, RGBAFormat, LinearFilter, Mesh, BufferGeometry, Float32BufferAttribute, Vector2, Vector3, MeshBasicMaterial, MeshPhongMaterial, Matrix4, Quaternion, NearestFilter, Raycaster, DoubleSide, Uint32BufferAttribute, Frustum, Color } from 'three';
2
-
3
- /*! *****************************************************************************
4
- Copyright (c) Microsoft Corporation.
5
-
6
- Permission to use, copy, modify, and/or distribute this software for any
7
- purpose with or without fee is hereby granted.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
- PERFORMANCE OF THIS SOFTWARE.
16
- ***************************************************************************** */
17
-
18
- function __awaiter(thisArg, _arguments, P, generator) {
19
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
20
- return new (P || (P = Promise))(function (resolve, reject) {
21
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
22
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
23
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
24
- step((generator = generator.apply(thisArg, _arguments || [])).next());
25
- });
26
- }
27
-
28
- class MapProvider {
29
- constructor() {
30
- this.name = '';
31
- this.minZoom = 0;
32
- this.maxZoom = 20;
33
- this.bounds = [];
34
- this.center = [];
35
- }
36
- fetchTile(zoom, x, y) {
37
- return null;
38
- }
39
- getMetaData() {
40
- return __awaiter(this, void 0, void 0, function* () { });
41
- }
42
- }
43
-
44
- class OpenStreetMapsProvider extends MapProvider {
45
- constructor(address = 'https://a.tile.openstreetmap.org/') {
46
- super();
47
- this.address = address;
48
- this.format = 'png';
49
- this.maxZoom = 19;
50
- }
51
- fetchTile(zoom, x, y) {
52
- return new Promise((resolve, reject) => {
53
- const image = document.createElement('img');
54
- image.onload = function () {
55
- resolve(image);
56
- };
57
- image.onerror = function () {
58
- reject();
59
- };
60
- image.crossOrigin = 'Anonymous';
61
- image.src = this.address + zoom + '/' + x + '/' + y + '.' + this.format;
62
- });
63
- }
64
- }
65
-
66
- class CanvasUtils {
67
- static createOffscreenCanvas(width, height) {
68
- if (typeof OffscreenCanvas !== 'undefined') {
69
- return new OffscreenCanvas(width, height);
70
- }
71
- else {
72
- let canvas = document.createElement('canvas');
73
- canvas.width = width;
74
- canvas.height = height;
75
- return canvas;
76
- }
77
- }
78
- }
79
-
80
- class TextureUtils {
81
- static createFillTexture(color = '#000000', width = 1, height = 1) {
82
- const canvas = CanvasUtils.createOffscreenCanvas(width, height);
83
- const context = canvas.getContext('2d');
84
- context.fillStyle = color;
85
- context.fillRect(0, 0, width, height);
86
- const texture = new Texture(canvas);
87
- texture.format = RGBAFormat;
88
- texture.magFilter = LinearFilter;
89
- texture.minFilter = LinearFilter;
90
- texture.generateMipmaps = false;
91
- texture.needsUpdate = true;
92
- return texture;
93
- }
94
- }
95
-
96
- class QuadTreePosition {
97
- }
98
- QuadTreePosition.root = -1;
99
- QuadTreePosition.topLeft = 0;
100
- QuadTreePosition.topRight = 1;
101
- QuadTreePosition.bottomLeft = 2;
102
- QuadTreePosition.bottomRight = 3;
103
- class MapNode extends Mesh {
104
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0, geometry = null, material = null) {
105
- super(geometry, material);
106
- this.mapView = null;
107
- this.parentNode = null;
108
- this.subdivided = false;
109
- this.disposed = false;
110
- this.nodesLoaded = 0;
111
- this.childrenCache = null;
112
- this.isMesh = true;
113
- this.mapView = mapView;
114
- this.parentNode = parentNode;
115
- this.disposed = false;
116
- this.location = location;
117
- this.level = level;
118
- this.x = x;
119
- this.y = y;
120
- this.initialize();
121
- }
122
- initialize() {
123
- return __awaiter(this, void 0, void 0, function* () { });
124
- }
125
- createChildNodes() { }
126
- subdivide() {
127
- const maxZoom = this.mapView.maxZoom();
128
- if (this.children.length > 0 || this.level + 1 > maxZoom || this.parentNode !== null && this.parentNode.nodesLoaded < MapNode.childrens) {
129
- return;
130
- }
131
- if (this.mapView.cacheTiles && this.childrenCache !== null) {
132
- this.isMesh = false;
133
- this.children = this.childrenCache;
134
- this.nodesLoaded = this.childrenCache.length;
135
- }
136
- else {
137
- this.createChildNodes();
138
- }
139
- this.subdivided = true;
140
- }
141
- simplify() {
142
- const minZoom = this.mapView.minZoom();
143
- if (this.level - 1 < minZoom) {
144
- return;
145
- }
146
- if (this.mapView.cacheTiles) {
147
- this.childrenCache = this.children;
148
- }
149
- else {
150
- for (let i = 0; i < this.children.length; i++) {
151
- this.children[i].dispose();
152
- }
153
- }
154
- this.subdivided = false;
155
- this.isMesh = true;
156
- this.children = [];
157
- this.nodesLoaded = 0;
158
- }
159
- loadData() {
160
- return __awaiter(this, void 0, void 0, function* () {
161
- if (this.level < this.mapView.provider.minZoom || this.level > this.mapView.provider.maxZoom) {
162
- console.warn('Geo-Three: Loading tile outside of provider range.', this);
163
- this.material.map = MapNode.defaultTexture;
164
- this.material.needsUpdate = true;
165
- return;
166
- }
167
- try {
168
- const image = yield this.mapView.provider.fetchTile(this.level, this.x, this.y);
169
- if (this.disposed) {
170
- return;
171
- }
172
- const texture = new Texture(image);
173
- texture.generateMipmaps = false;
174
- texture.format = RGBAFormat;
175
- texture.magFilter = LinearFilter;
176
- texture.minFilter = LinearFilter;
177
- texture.needsUpdate = true;
178
- this.material.alphaTest = 0.5
179
- this.material.map = texture;
180
- }
181
- catch (e) {
182
- if (this.disposed) {
183
- return;
184
- }
185
- console.warn('Geo-Three: Failed to load node tile data.', this);
186
- this.material.map = MapNode.defaultTexture;
187
- }
188
- this.material.needsUpdate = true;
189
- });
190
- }
191
- nodeReady() {
192
- if (this.disposed) {
193
- console.warn('Geo-Three: nodeReady() called for disposed node.', this);
194
- this.dispose();
195
- return;
196
- }
197
- if (this.parentNode !== null) {
198
- this.parentNode.nodesLoaded++;
199
- if (this.parentNode.nodesLoaded === MapNode.childrens) {
200
- if (this.parentNode.subdivided === true) {
201
- this.parentNode.isMesh = false;
202
- }
203
- for (let i = 0; i < this.parentNode.children.length; i++) {
204
- this.parentNode.children[i].visible = true;
205
- }
206
- }
207
- if (this.parentNode.nodesLoaded > MapNode.childrens) {
208
- console.error('Geo-Three: Loaded more children objects than expected.', this.parentNode.nodesLoaded, this);
209
- }
210
- }
211
- else {
212
- this.visible = true;
213
- }
214
- }
215
- dispose() {
216
- this.disposed = true;
217
- const self = this;
218
- try {
219
- const material = self.material;
220
- material.dispose();
221
- }
222
- catch (e) { }
223
- try {
224
- self.geometry.dispose();
225
- }
226
- catch (e) { }
227
- }
228
- }
229
- MapNode.defaultTexture = TextureUtils.createFillTexture();
230
- MapNode.baseGeometry = null;
231
- MapNode.baseScale = null;
232
- MapNode.childrens = 4;
233
-
234
- class MapNodeGeometry extends BufferGeometry {
235
- constructor(width = 1.0, height = 1.0, widthSegments = 1.0, heightSegments = 1.0, skirt = false, skirtDepth = 10.0) {
236
- super();
237
- const indices = [];
238
- const vertices = [];
239
- const normals = [];
240
- const uvs = [];
241
- MapNodeGeometry.buildPlane(width, height, widthSegments, heightSegments, indices, vertices, normals, uvs);
242
- if (skirt) {
243
- MapNodeGeometry.buildSkirt(width, height, widthSegments, heightSegments, skirtDepth, indices, vertices, normals, uvs);
244
- }
245
- this.setIndex(indices);
246
- this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
247
- this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
248
- this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
249
- }
250
- static buildPlane(width = 1.0, height = 1.0, widthSegments = 1.0, heightSegments = 1.0, indices, vertices, normals, uvs) {
251
- const widthHalf = width / 2;
252
- const heightHalf = height / 2;
253
- const gridX = widthSegments + 1;
254
- const gridZ = heightSegments + 1;
255
- const segmentWidth = width / widthSegments;
256
- const segmentHeight = height / heightSegments;
257
- for (let iz = 0; iz < gridZ; iz++) {
258
- const z = iz * segmentHeight - heightHalf;
259
- for (let ix = 0; ix < gridX; ix++) {
260
- const x = ix * segmentWidth - widthHalf;
261
- vertices.push(x, 0, z);
262
- normals.push(0, 1, 0);
263
- uvs.push(ix / widthSegments, 1 - iz / heightSegments);
264
- }
265
- }
266
- for (let iz = 0; iz < heightSegments; iz++) {
267
- for (let ix = 0; ix < widthSegments; ix++) {
268
- const a = ix + gridX * iz;
269
- const b = ix + gridX * (iz + 1);
270
- const c = ix + 1 + gridX * (iz + 1);
271
- const d = ix + 1 + gridX * iz;
272
- indices.push(a, b, d, b, c, d);
273
- }
274
- }
275
- }
276
- static buildSkirt(width = 1.0, height = 1.0, widthSegments = 1.0, heightSegments = 1.0, skirtDepth, indices, vertices, normals, uvs) {
277
- const widthHalf = width / 2;
278
- const heightHalf = height / 2;
279
- const gridX = widthSegments + 1;
280
- const gridZ = heightSegments + 1;
281
- const segmentWidth = width / widthSegments;
282
- const segmentHeight = height / heightSegments;
283
- let start = vertices.length / 3;
284
- for (let ix = 0; ix < gridX; ix++) {
285
- const x = ix * segmentWidth - widthHalf;
286
- const z = -heightHalf;
287
- vertices.push(x, -skirtDepth, z);
288
- normals.push(0, 1, 0);
289
- uvs.push(ix / widthSegments, 1);
290
- }
291
- for (let ix = 0; ix < widthSegments; ix++) {
292
- const a = ix;
293
- const d = ix + 1;
294
- const b = ix + start;
295
- const c = ix + start + 1;
296
- indices.push(d, b, a, d, c, b);
297
- }
298
- start = vertices.length / 3;
299
- for (let ix = 0; ix < gridX; ix++) {
300
- const x = ix * segmentWidth - widthHalf;
301
- const z = heightSegments * segmentHeight - heightHalf;
302
- vertices.push(x, -skirtDepth, z);
303
- normals.push(0, 1, 0);
304
- uvs.push(ix / widthSegments, 0);
305
- }
306
- let offset = gridX * gridZ - widthSegments - 1;
307
- for (let ix = 0; ix < widthSegments; ix++) {
308
- const a = offset + ix;
309
- const d = offset + ix + 1;
310
- const b = ix + start;
311
- const c = ix + start + 1;
312
- indices.push(a, b, d, b, c, d);
313
- }
314
- start = vertices.length / 3;
315
- for (let iz = 0; iz < gridZ; iz++) {
316
- const z = iz * segmentHeight - heightHalf;
317
- const x = -widthHalf;
318
- vertices.push(x, -skirtDepth, z);
319
- normals.push(0, 1, 0);
320
- uvs.push(0, 1 - iz / heightSegments);
321
- }
322
- for (let iz = 0; iz < heightSegments; iz++) {
323
- const a = iz * gridZ;
324
- const d = (iz + 1) * gridZ;
325
- const b = iz + start;
326
- const c = iz + start + 1;
327
- indices.push(a, b, d, b, c, d);
328
- }
329
- start = vertices.length / 3;
330
- for (let iz = 0; iz < gridZ; iz++) {
331
- const z = iz * segmentHeight - heightHalf;
332
- const x = widthSegments * segmentWidth - widthHalf;
333
- vertices.push(x, -skirtDepth, z);
334
- normals.push(0, 1, 0);
335
- uvs.push(1.0, 1 - iz / heightSegments);
336
- }
337
- for (let iz = 0; iz < heightSegments; iz++) {
338
- const a = iz * gridZ + heightSegments;
339
- const d = (iz + 1) * gridZ + heightSegments;
340
- const b = iz + start;
341
- const c = iz + start + 1;
342
- indices.push(d, b, a, d, c, b);
343
- }
344
- }
345
- }
346
-
347
- class Geolocation {
348
- constructor(latitude, longitude) {
349
- this.latitude = latitude;
350
- this.longitude = longitude;
351
- }
352
- }
353
-
354
- class UnitsUtils {
355
- static datumsToSpherical(latitude, longitude) {
356
- const x = longitude * UnitsUtils.EARTH_ORIGIN / 180.0;
357
- let y = Math.log(Math.tan((90 + latitude) * Math.PI / 360.0)) / (Math.PI / 180.0);
358
- y = y * UnitsUtils.EARTH_ORIGIN / 180.0;
359
- return new Vector2(x, y);
360
- }
361
- static sphericalToDatums(x, y) {
362
- const longitude = x / UnitsUtils.EARTH_ORIGIN * 180.0;
363
- let latitude = y / UnitsUtils.EARTH_ORIGIN * 180.0;
364
- latitude = 180.0 / Math.PI * (2 * Math.atan(Math.exp(latitude * Math.PI / 180.0)) - Math.PI / 2.0);
365
- return new Geolocation(latitude, longitude);
366
- }
367
- static quadtreeToDatums(zoom, x, y) {
368
- const n = Math.pow(2.0, zoom);
369
- const longitude = x / n * 360.0 - 180.0;
370
- const latitudeRad = Math.atan(Math.sinh(Math.PI * (1.0 - 2.0 * y / n)));
371
- const latitude = 180.0 * (latitudeRad / Math.PI);
372
- return new Geolocation(latitude, longitude);
373
- }
374
- static vectorToDatums(dir) {
375
- const radToDeg = 180 / Math.PI;
376
- const latitude = Math.atan2(dir.y, Math.sqrt(Math.pow(dir.x, 2) + Math.pow(-dir.z, 2))) * radToDeg;
377
- const longitude = Math.atan2(-dir.z, dir.x) * radToDeg;
378
- return new Geolocation(latitude, longitude);
379
- }
380
- static datumsToVector(latitude, longitude) {
381
- const degToRad = Math.PI / 180;
382
- const rotX = longitude * degToRad;
383
- const rotY = latitude * degToRad;
384
- var cos = Math.cos(rotY);
385
- return new Vector3(-Math.cos(rotX + Math.PI) * cos, Math.sin(rotY), Math.sin(rotX + Math.PI) * cos);
386
- }
387
- static mapboxAltitude(color) {
388
- return (color.r * 255.0 * 65536.0 + color.g * 255.0 * 256.0 + color.b * 255.0) * 0.1 - 10000.0;
389
- }
390
- }
391
- UnitsUtils.EARTH_RADIUS = 6371008;
392
- UnitsUtils.EARTH_RADIUS_A = 6378137.0;
393
- UnitsUtils.EARTH_RADIUS_B = 6356752.314245;
394
- UnitsUtils.EARTH_PERIMETER = 2 * Math.PI * UnitsUtils.EARTH_RADIUS;
395
- UnitsUtils.EARTH_ORIGIN = UnitsUtils.EARTH_PERIMETER / 2.0;
396
-
397
- class MapPlaneNode extends MapNode {
398
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0) {
399
- super(parentNode, mapView, location, level, x, y, MapPlaneNode.geometry, new MeshBasicMaterial({ wireframe: false,color: 0xffffff }));
400
- this.matrixAutoUpdate = false;
401
- this.isMesh = true;
402
- this.visible = false;
403
- }
404
- initialize() {
405
- const _super = Object.create(null, {
406
- initialize: { get: () => super.initialize }
407
- });
408
- return __awaiter(this, void 0, void 0, function* () {
409
- _super.initialize.call(this);
410
- yield this.loadData();
411
- this.nodeReady();
412
- });
413
- }
414
- createChildNodes() {
415
- const level = this.level + 1;
416
- const x = this.x * 2;
417
- const y = this.y * 2;
418
- const Constructor = Object.getPrototypeOf(this).constructor;
419
- let node = new Constructor(this, this.mapView, QuadTreePosition.topLeft, level, x, y);
420
- node.scale.set(0.5, 1.0, 0.5);
421
- node.position.set(-0.25, 0, -0.25);
422
- this.add(node);
423
- node.updateMatrix();
424
- node.updateMatrixWorld(true);
425
- node = new Constructor(this, this.mapView, QuadTreePosition.topRight, level, x + 1, y);
426
- node.scale.set(0.5, 1.0, 0.5);
427
- node.position.set(0.25, 0, -0.25);
428
- this.add(node);
429
- node.updateMatrix();
430
- node.updateMatrixWorld(true);
431
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomLeft, level, x, y + 1);
432
- node.scale.set(0.5, 1.0, 0.5);
433
- node.position.set(-0.25, 0, 0.25);
434
- this.add(node);
435
- node.updateMatrix();
436
- node.updateMatrixWorld(true);
437
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomRight, level, x + 1, y + 1);
438
- node.scale.set(0.5, 1.0, 0.5);
439
- node.position.set(0.25, 0, 0.25);
440
- this.add(node);
441
- node.updateMatrix();
442
- node.updateMatrixWorld(true);
443
- }
444
- raycast(raycaster, intersects) {
445
- if (this.isMesh === true) {
446
- super.raycast(raycaster, intersects);
447
- }
448
- }
449
- }
450
- MapPlaneNode.geometry = new MapNodeGeometry(1, 1, 1, 1, false);
451
- MapPlaneNode.baseGeometry = MapPlaneNode.geometry;
452
- MapPlaneNode.baseScale = new Vector3(UnitsUtils.EARTH_PERIMETER, 1.0, UnitsUtils.EARTH_PERIMETER);
453
-
454
- class MapNodeHeightGeometry extends BufferGeometry {
455
- constructor(width = 1.0, height = 1.0, widthSegments = 1.0, heightSegments = 1.0, skirt = false, skirtDepth = 10.0, imageData = null, calculateNormals = true) {
456
- super();
457
- const indices = [];
458
- const vertices = [];
459
- const normals = [];
460
- const uvs = [];
461
- MapNodeGeometry.buildPlane(width, height, widthSegments, heightSegments, indices, vertices, normals, uvs);
462
- const data = imageData.data;
463
- for (let i = 0, j = 0; i < data.length && j < vertices.length; i += 4, j += 3) {
464
- const r = data[i];
465
- const g = data[i + 1];
466
- const b = data[i + 2];
467
- const value = (r * 65536 + g * 256 + b) * 0.1 - 1e4;
468
- vertices[j + 1] = value;
469
- }
470
- if (skirt) {
471
- MapNodeGeometry.buildSkirt(width, height, widthSegments, heightSegments, skirtDepth, indices, vertices, normals, uvs);
472
- }
473
- this.setIndex(indices);
474
- this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
475
- this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
476
- this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
477
- if (calculateNormals) {
478
- this.computeNormals(widthSegments, heightSegments);
479
- }
480
- }
481
- computeNormals(widthSegments, heightSegments) {
482
- const positionAttribute = this.getAttribute('position');
483
- if (positionAttribute !== undefined) {
484
- let normalAttribute = this.getAttribute('normal');
485
- const normalLength = heightSegments * widthSegments;
486
- for (let i = 0; i < normalLength; i++) {
487
- normalAttribute.setXYZ(i, 0, 0, 0);
488
- }
489
- const pA = new Vector3(), pB = new Vector3(), pC = new Vector3();
490
- const nA = new Vector3(), nB = new Vector3(), nC = new Vector3();
491
- const cb = new Vector3(), ab = new Vector3();
492
- const indexLength = heightSegments * widthSegments * 6;
493
- for (let i = 0; i < indexLength; i += 3) {
494
- const vA = this.index.getX(i + 0);
495
- const vB = this.index.getX(i + 1);
496
- const vC = this.index.getX(i + 2);
497
- pA.fromBufferAttribute(positionAttribute, vA);
498
- pB.fromBufferAttribute(positionAttribute, vB);
499
- pC.fromBufferAttribute(positionAttribute, vC);
500
- cb.subVectors(pC, pB);
501
- ab.subVectors(pA, pB);
502
- cb.cross(ab);
503
- nA.fromBufferAttribute(normalAttribute, vA);
504
- nB.fromBufferAttribute(normalAttribute, vB);
505
- nC.fromBufferAttribute(normalAttribute, vC);
506
- nA.add(cb);
507
- nB.add(cb);
508
- nC.add(cb);
509
- normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z);
510
- normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z);
511
- normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z);
512
- }
513
- this.normalizeNormals();
514
- normalAttribute.needsUpdate = true;
515
- }
516
- }
517
- }
518
-
519
- class MapHeightNode extends MapNode {
520
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0, geometry = MapHeightNode.geometry, material = new MeshPhongMaterial({ wireframe: false, color: 0xffffff })) {
521
- super(parentNode, mapView, location, level, x, y, geometry, material);
522
- this.heightLoaded = false;
523
- this.textureLoaded = false;
524
- this.geometrySize = 16;
525
- this.geometryNormals = false;
526
- this.isMesh = true;
527
- this.visible = false;
528
- this.matrixAutoUpdate = false;
529
- }
530
- initialize() {
531
- const _super = Object.create(null, {
532
- initialize: { get: () => super.initialize }
533
- });
534
- return __awaiter(this, void 0, void 0, function* () {
535
- _super.initialize.call(this);
536
- yield this.loadData();
537
- yield this.loadHeightGeometry();
538
- this.nodeReady();
539
- });
540
- }
541
- loadData() {
542
- const _super = Object.create(null, {
543
- loadData: { get: () => super.loadData }
544
- });
545
- return __awaiter(this, void 0, void 0, function* () {
546
- yield _super.loadData.call(this);
547
- this.textureLoaded = true;
548
- });
549
- }
550
- loadHeightGeometry() {
551
- return __awaiter(this, void 0, void 0, function* () {
552
- if (this.mapView.heightProvider === null) {
553
- throw new Error('GeoThree: MapView.heightProvider provider is null.');
554
- }
555
- if (this.level < this.mapView.heightProvider.minZoom || this.level > this.mapView.heightProvider.maxZoom) {
556
- console.warn('Geo-Three: Loading tile outside of provider range.', this);
557
- this.geometry = MapPlaneNode.baseGeometry;
558
- return;
559
- }
560
- try {
561
- const image = yield this.mapView.heightProvider.fetchTile(this.level, this.x, this.y);
562
- if (this.disposed) {
563
- return;
564
- }
565
- const canvas = CanvasUtils.createOffscreenCanvas(this.geometrySize + 1, this.geometrySize + 1);
566
- const context = canvas.getContext('2d');
567
- context.imageSmoothingEnabled = false;
568
- context.drawImage(image, 0, 0, MapHeightNode.tileSize, MapHeightNode.tileSize, 0, 0, canvas.width, canvas.height);
569
- const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
570
- this.geometry = new MapNodeHeightGeometry(1, 1, this.geometrySize, this.geometrySize, true, 10.0, imageData, true);
571
- }
572
- catch (e) {
573
- if (this.disposed) {
574
- return;
575
- }
576
- this.geometry = MapPlaneNode.baseGeometry;
577
- }
578
- this.heightLoaded = true;
579
- });
580
- }
581
- createChildNodes() {
582
- const level = this.level + 1;
583
- const Constructor = Object.getPrototypeOf(this).constructor;
584
- const x = this.x * 2;
585
- const y = this.y * 2;
586
- let node = new Constructor(this, this.mapView, QuadTreePosition.topLeft, level, x, y);
587
- node.scale.set(0.5, 1.0, 0.5);
588
- node.position.set(-0.25, 0, -0.25);
589
- this.add(node);
590
- node.updateMatrix();
591
- node.updateMatrixWorld(true);
592
- node = new Constructor(this, this.mapView, QuadTreePosition.topRight, level, x + 1, y);
593
- node.scale.set(0.5, 1.0, 0.5);
594
- node.position.set(0.25, 0, -0.25);
595
- this.add(node);
596
- node.updateMatrix();
597
- node.updateMatrixWorld(true);
598
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomLeft, level, x, y + 1);
599
- node.scale.set(0.5, 1.0, 0.5);
600
- node.position.set(-0.25, 0, 0.25);
601
- this.add(node);
602
- node.updateMatrix();
603
- node.updateMatrixWorld(true);
604
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomRight, level, x + 1, y + 1);
605
- node.scale.set(0.5, 1.0, 0.5);
606
- node.position.set(0.25, 0, 0.25);
607
- this.add(node);
608
- node.updateMatrix();
609
- node.updateMatrixWorld(true);
610
- }
611
- raycast(raycaster, intersects) {
612
- if (this.isMesh === true) {
613
- super.raycast(raycaster, intersects);
614
- }
615
- }
616
- }
617
- MapHeightNode.tileSize = 256;
618
- MapHeightNode.geometry = new MapNodeGeometry(1, 1, 1, 1);
619
- MapHeightNode.baseGeometry = MapPlaneNode.geometry;
620
- MapHeightNode.baseScale = new Vector3(UnitsUtils.EARTH_PERIMETER, 1, UnitsUtils.EARTH_PERIMETER);
621
-
622
- class MapSphereNodeGeometry extends BufferGeometry {
623
- constructor(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
624
- super();
625
- const thetaEnd = thetaStart + thetaLength;
626
- let index = 0;
627
- const grid = [];
628
- const vertex = new Vector3();
629
- const normal = new Vector3();
630
- const indices = [];
631
- const vertices = [];
632
- const normals = [];
633
- const uvs = [];
634
- for (let iy = 0; iy <= heightSegments; iy++) {
635
- const verticesRow = [];
636
- const v = iy / heightSegments;
637
- for (let ix = 0; ix <= widthSegments; ix++) {
638
- const u = ix / widthSegments;
639
- vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
640
- vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
641
- vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
642
- vertices.push(vertex.x, vertex.y, vertex.z);
643
- normal.set(vertex.x, vertex.y, vertex.z).normalize();
644
- normals.push(normal.x, normal.y, normal.z);
645
- uvs.push(u, 1 - v);
646
- verticesRow.push(index++);
647
- }
648
- grid.push(verticesRow);
649
- }
650
- for (let iy = 0; iy < heightSegments; iy++) {
651
- for (let ix = 0; ix < widthSegments; ix++) {
652
- const a = grid[iy][ix + 1];
653
- const b = grid[iy][ix];
654
- const c = grid[iy + 1][ix];
655
- const d = grid[iy + 1][ix + 1];
656
- if (iy !== 0 || thetaStart > 0) {
657
- indices.push(a, b, d);
658
- }
659
- if (iy !== heightSegments - 1 || thetaEnd < Math.PI) {
660
- indices.push(b, c, d);
661
- }
662
- }
663
- }
664
- this.setIndex(indices);
665
- this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
666
- this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
667
- this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
668
- }
669
- }
670
-
671
- class MapSphereNode extends MapNode {
672
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0) {
673
- super(parentNode, mapView, location, level, x, y, MapSphereNode.createGeometry(level, x, y), new MeshBasicMaterial({ wireframe: false,color: 0xffffff }));
674
- this.applyScaleNode();
675
- this.matrixAutoUpdate = false;
676
- this.isMesh = true;
677
- this.visible = false;
678
- }
679
- initialize() {
680
- const _super = Object.create(null, {
681
- initialize: { get: () => super.initialize }
682
- });
683
- return __awaiter(this, void 0, void 0, function* () {
684
- _super.initialize.call(this);
685
- yield this.loadData();
686
- this.nodeReady();
687
- });
688
- }
689
- static createGeometry(zoom, x, y) {
690
- const range = Math.pow(2, zoom);
691
- const max = 40;
692
- const segments = Math.floor(MapSphereNode.segments * (max / (zoom + 1)) / max);
693
- const phiLength = 1 / range * 2 * Math.PI;
694
- const phiStart = x * phiLength;
695
- const thetaLength = 1 / range * Math.PI;
696
- const thetaStart = y * thetaLength;
697
- return new MapSphereNodeGeometry(1, segments, segments, phiStart, phiLength, thetaStart, thetaLength);
698
- }
699
- applyScaleNode() {
700
- this.geometry.computeBoundingBox();
701
- const box = this.geometry.boundingBox.clone();
702
- const center = box.getCenter(new Vector3());
703
- const matrix = new Matrix4();
704
- matrix.compose(new Vector3(-center.x, -center.y, -center.z), new Quaternion(), new Vector3(UnitsUtils.EARTH_RADIUS, UnitsUtils.EARTH_RADIUS, UnitsUtils.EARTH_RADIUS));
705
- this.geometry.applyMatrix4(matrix);
706
- this.position.copy(center);
707
- this.updateMatrix();
708
- this.updateMatrixWorld();
709
- }
710
- updateMatrix() {
711
- this.matrix.setPosition(this.position);
712
- this.matrixWorldNeedsUpdate = true;
713
- }
714
- updateMatrixWorld(force = false) {
715
- if (this.matrixWorldNeedsUpdate || force) {
716
- this.matrixWorld.copy(this.matrix);
717
- this.matrixWorldNeedsUpdate = false;
718
- }
719
- }
720
- createChildNodes() {
721
- const level = this.level + 1;
722
- const x = this.x * 2;
723
- const y = this.y * 2;
724
- const Constructor = Object.getPrototypeOf(this).constructor;
725
- let node = new Constructor(this, this.mapView, QuadTreePosition.topLeft, level, x, y);
726
- this.add(node);
727
- node = new Constructor(this, this.mapView, QuadTreePosition.topRight, level, x + 1, y);
728
- this.add(node);
729
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomLeft, level, x, y + 1);
730
- this.add(node);
731
- node = new Constructor(this, this.mapView, QuadTreePosition.bottomRight, level, x + 1, y + 1);
732
- this.add(node);
733
- }
734
- raycast(raycaster, intersects) {
735
- if (this.isMesh === true) {
736
- super.raycast(raycaster, intersects);
737
- }
738
- }
739
- }
740
- MapSphereNode.baseGeometry = new MapSphereNodeGeometry(UnitsUtils.EARTH_RADIUS, 64, 64, 0, 2 * Math.PI, 0, Math.PI);
741
- MapSphereNode.baseScale = new Vector3(1, 1, 1);
742
- MapSphereNode.segments = 80;
743
-
744
- class MapHeightNodeShader extends MapHeightNode {
745
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0) {
746
- const material = MapHeightNodeShader.prepareMaterial(new MeshPhongMaterial({ map: MapNode.defaultTexture, color: 0xFFFFFF }));
747
- super(parentNode, mapView, location, level, x, y, MapHeightNodeShader.geometry, material);
748
- this.frustumCulled = false;
749
- }
750
- static prepareMaterial(material) {
751
- material.userData = { heightMap: { value: MapHeightNodeShader.defaultHeightTexture } };
752
- material.onBeforeCompile = (shader) => {
753
- for (const i in material.userData) {
754
- shader.uniforms[i] = material.userData[i];
755
- }
756
- shader.vertexShader =
757
- `
758
- uniform sampler2D heightMap;
759
- ` + shader.vertexShader;
760
- shader.vertexShader = shader.vertexShader.replace('#include <fog_vertex>', `
761
- #include <fog_vertex>
762
-
763
- // Calculate height of the title
764
- vec4 _theight = texture2D(heightMap, vUv);
765
- float _height = ((_theight.r * 255.0 * 65536.0 + _theight.g * 255.0 * 256.0 + _theight.b * 255.0) * 0.1) - 10000.0;
766
- vec3 _transformed = position + _height * normal;
767
-
768
- // Vertex position based on height
769
- gl_Position = projectionMatrix * modelViewMatrix * vec4(_transformed, 1.0);
770
- `);
771
- };
772
- return material;
773
- }
774
- loadData() {
775
- const _super = Object.create(null, {
776
- loadData: { get: () => super.loadData }
777
- });
778
- return __awaiter(this, void 0, void 0, function* () {
779
- yield _super.loadData.call(this);
780
- this.textureLoaded = true;
781
- });
782
- }
783
- loadHeightGeometry() {
784
- return __awaiter(this, void 0, void 0, function* () {
785
- if (this.mapView.heightProvider === null) {
786
- throw new Error('GeoThree: MapView.heightProvider provider is null.');
787
- }
788
- if (this.level < this.mapView.heightProvider.minZoom || this.level > this.mapView.heightProvider.maxZoom) {
789
- console.warn('Geo-Three: Loading tile outside of provider range.', this);
790
- this.material.map = MapHeightNodeShader.defaultTexture;
791
- this.material.needsUpdate = true;
792
- return;
793
- }
794
- try {
795
- const image = yield this.mapView.heightProvider.fetchTile(this.level, this.x, this.y);
796
- if (this.disposed) {
797
- return;
798
- }
799
- const texture = new Texture(image);
800
- texture.generateMipmaps = false;
801
- texture.format = RGBAFormat;
802
- texture.magFilter = NearestFilter;
803
- texture.minFilter = NearestFilter;
804
- texture.needsUpdate = true;
805
- this.material.userData.heightMap.value = texture;
806
- }
807
- catch (e) {
808
- if (this.disposed) {
809
- return;
810
- }
811
- console.error('Geo-Three: Failed to load node tile height data.', this);
812
- this.material.userData.heightMap.value = MapHeightNodeShader.defaultHeightTexture;
813
- }
814
- this.material.needsUpdate = true;
815
- this.heightLoaded = true;
816
- });
817
- }
818
- raycast(raycaster, intersects) {
819
- if (this.isMesh === true) {
820
- this.geometry = MapPlaneNode.geometry;
821
- super.raycast(raycaster, intersects);
822
- this.geometry = MapHeightNodeShader.geometry;
823
- }
824
- }
825
- }
826
- MapHeightNodeShader.defaultHeightTexture = TextureUtils.createFillTexture('#0186C0');
827
- MapHeightNodeShader.geometrySize = 256;
828
- MapHeightNodeShader.geometry = new MapNodeGeometry(1.0, 1.0, MapHeightNodeShader.geometrySize, MapHeightNodeShader.geometrySize, true);
829
- MapHeightNodeShader.baseGeometry = MapPlaneNode.geometry;
830
- MapHeightNodeShader.baseScale = new Vector3(UnitsUtils.EARTH_PERIMETER, 1, UnitsUtils.EARTH_PERIMETER);
831
-
832
- class LODRaycast {
833
- constructor() {
834
- this.subdivisionRays = 1;
835
- this.thresholdUp = 0.6;
836
- this.thresholdDown = 0.15;
837
- this.raycaster = new Raycaster();
838
- this.mouse = new Vector2();
839
- this.powerDistance = false;
840
- this.scaleDistance = true;
841
- }
842
- updateLOD(view, camera, renderer, scene) {
843
- const intersects = [];
844
- for (let t = 0; t < this.subdivisionRays; t++) {
845
- this.mouse.set(Math.random() * 2 - 1, Math.random() * 2 - 1);
846
- this.raycaster.setFromCamera(this.mouse, camera);
847
- this.raycaster.intersectObjects(view.children, true, intersects);
848
- }
849
- for (let i = 0; i < intersects.length; i++) {
850
- const node = intersects[i].object;
851
- let distance = intersects[i].distance;
852
- if (this.powerDistance) {
853
- distance = Math.pow(distance * 2, node.level);
854
- }
855
- if (this.scaleDistance) {
856
- const matrix = node.matrixWorld.elements;
857
- const vector = new Vector3(matrix[0], matrix[1], matrix[2]);
858
- distance = vector.length() / distance;
859
- }
860
- if (distance > this.thresholdUp) {
861
- node.subdivide();
862
- }
863
- else if (distance < this.thresholdDown && node.parentNode) {
864
- node.parentNode.simplify();
865
- }
866
- }
867
- }
868
- }
869
-
870
- class Martini {
871
- constructor(gridSize = 257) {
872
- this.gridSize = gridSize;
873
- const tileSize = gridSize - 1;
874
- if (tileSize & tileSize - 1) {
875
- throw new Error(`Expected grid size to be 2^n+1, got ${gridSize}.`);
876
- }
877
- this.numTriangles = tileSize * tileSize * 2 - 2;
878
- this.numParentTriangles = this.numTriangles - tileSize * tileSize;
879
- this.indices = new Uint32Array(this.gridSize * this.gridSize);
880
- this.coords = new Uint16Array(this.numTriangles * 4);
881
- for (let i = 0; i < this.numTriangles; i++) {
882
- let id = i + 2;
883
- let ax = 0, ay = 0, bx = 0, by = 0, cx = 0, cy = 0;
884
- if (id & 1) {
885
- bx = by = cx = tileSize;
886
- }
887
- else {
888
- ax = ay = cy = tileSize;
889
- }
890
- while ((id >>= 1) > 1) {
891
- const mx = ax + bx >> 1;
892
- const my = ay + by >> 1;
893
- if (id & 1) {
894
- bx = ax;
895
- by = ay;
896
- ax = cx;
897
- ay = cy;
898
- }
899
- else {
900
- ax = bx;
901
- ay = by;
902
- bx = cx;
903
- by = cy;
904
- }
905
- cx = mx;
906
- cy = my;
907
- }
908
- const k = i * 4;
909
- this.coords[k + 0] = ax;
910
- this.coords[k + 1] = ay;
911
- this.coords[k + 2] = bx;
912
- this.coords[k + 3] = by;
913
- }
914
- }
915
- createTile(terrain) {
916
- return new Tile(terrain, this);
917
- }
918
- }
919
- class Tile {
920
- constructor(terrain, martini) {
921
- const size = martini.gridSize;
922
- if (terrain.length !== size * size) {
923
- throw new Error(`Expected terrain data of length ${size * size} (${size} x ${size}), got ${terrain.length}.`);
924
- }
925
- this.terrain = terrain;
926
- this.martini = martini;
927
- this.errors = new Float32Array(terrain.length);
928
- this.update();
929
- }
930
- update() {
931
- const { numTriangles, numParentTriangles, coords, gridSize: size } = this.martini;
932
- const { terrain, errors } = this;
933
- for (let i = numTriangles - 1; i >= 0; i--) {
934
- const k = i * 4;
935
- const ax = coords[k + 0];
936
- const ay = coords[k + 1];
937
- const bx = coords[k + 2];
938
- const by = coords[k + 3];
939
- const mx = ax + bx >> 1;
940
- const my = ay + by >> 1;
941
- const cx = mx + my - ay;
942
- const cy = my + ax - mx;
943
- const interpolatedHeight = (terrain[ay * size + ax] + terrain[by * size + bx]) / 2;
944
- const middleIndex = my * size + mx;
945
- const middleError = Math.abs(interpolatedHeight - terrain[middleIndex]);
946
- errors[middleIndex] = Math.max(errors[middleIndex], middleError);
947
- if (i < numParentTriangles) {
948
- const leftChildIndex = (ay + cy >> 1) * size + (ax + cx >> 1);
949
- const rightChildIndex = (by + cy >> 1) * size + (bx + cx >> 1);
950
- errors[middleIndex] = Math.max(errors[middleIndex], errors[leftChildIndex], errors[rightChildIndex]);
951
- }
952
- }
953
- }
954
- getMesh(maxError = 0, withSkirts = false) {
955
- const { gridSize: size, indices } = this.martini;
956
- const { errors } = this;
957
- let numVertices = 0;
958
- let numTriangles = 0;
959
- const max = size - 1;
960
- let aIndex, bIndex, cIndex = 0;
961
- const leftSkirtIndices = [];
962
- const rightSkirtIndices = [];
963
- const bottomSkirtIndices = [];
964
- const topSkirtIndices = [];
965
- indices.fill(0);
966
- function countElements(ax, ay, bx, by, cx, cy) {
967
- const mx = ax + bx >> 1;
968
- const my = ay + by >> 1;
969
- if (Math.abs(ax - cx) + Math.abs(ay - cy) > 1 && errors[my * size + mx] > maxError) {
970
- countElements(cx, cy, ax, ay, mx, my);
971
- countElements(bx, by, cx, cy, mx, my);
972
- }
973
- else {
974
- aIndex = ay * size + ax;
975
- bIndex = by * size + bx;
976
- cIndex = cy * size + cx;
977
- if (indices[aIndex] === 0) {
978
- if (withSkirts) {
979
- if (ax === 0) {
980
- leftSkirtIndices.push(numVertices);
981
- }
982
- else if (ax === max) {
983
- rightSkirtIndices.push(numVertices);
984
- }
985
- if (ay === 0) {
986
- bottomSkirtIndices.push(numVertices);
987
- }
988
- else if (ay === max) {
989
- topSkirtIndices.push(numVertices);
990
- }
991
- }
992
- indices[aIndex] = ++numVertices;
993
- }
994
- if (indices[bIndex] === 0) {
995
- if (withSkirts) {
996
- if (bx === 0) {
997
- leftSkirtIndices.push(numVertices);
998
- }
999
- else if (bx === max) {
1000
- rightSkirtIndices.push(numVertices);
1001
- }
1002
- if (by === 0) {
1003
- bottomSkirtIndices.push(numVertices);
1004
- }
1005
- else if (by === max) {
1006
- topSkirtIndices.push(numVertices);
1007
- }
1008
- }
1009
- indices[bIndex] = ++numVertices;
1010
- }
1011
- if (indices[cIndex] === 0) {
1012
- if (withSkirts) {
1013
- if (cx === 0) {
1014
- leftSkirtIndices.push(numVertices);
1015
- }
1016
- else if (cx === max) {
1017
- rightSkirtIndices.push(numVertices);
1018
- }
1019
- if (cy === 0) {
1020
- bottomSkirtIndices.push(numVertices);
1021
- }
1022
- else if (cy === max) {
1023
- topSkirtIndices.push(numVertices);
1024
- }
1025
- }
1026
- indices[cIndex] = ++numVertices;
1027
- }
1028
- numTriangles++;
1029
- }
1030
- }
1031
- countElements(0, 0, max, max, max, 0);
1032
- countElements(max, max, 0, 0, 0, max);
1033
- let numTotalVertices = numVertices * 2;
1034
- let numTotalTriangles = numTriangles * 3;
1035
- if (withSkirts) {
1036
- numTotalVertices += (leftSkirtIndices.length + rightSkirtIndices.length + bottomSkirtIndices.length + topSkirtIndices.length) * 2;
1037
- numTotalTriangles += ((leftSkirtIndices.length - 1) * 2 + (rightSkirtIndices.length - 1) * 2 + (bottomSkirtIndices.length - 1) * 2 + (topSkirtIndices.length - 1) * 2) * 3;
1038
- }
1039
- const vertices = new Uint16Array(numTotalVertices);
1040
- const triangles = new Uint32Array(numTotalTriangles);
1041
- let triIndex = 0;
1042
- function processTriangle(ax, ay, bx, by, cx, cy) {
1043
- const mx = ax + bx >> 1;
1044
- const my = ay + by >> 1;
1045
- if (Math.abs(ax - cx) + Math.abs(ay - cy) > 1 && errors[my * size + mx] > maxError) {
1046
- processTriangle(cx, cy, ax, ay, mx, my);
1047
- processTriangle(bx, by, cx, cy, mx, my);
1048
- }
1049
- else {
1050
- const a = indices[ay * size + ax] - 1;
1051
- const b = indices[by * size + bx] - 1;
1052
- const c = indices[cy * size + cx] - 1;
1053
- vertices[2 * a] = ax;
1054
- vertices[2 * a + 1] = ay;
1055
- vertices[2 * b] = bx;
1056
- vertices[2 * b + 1] = by;
1057
- vertices[2 * c] = cx;
1058
- vertices[2 * c + 1] = cy;
1059
- triangles[triIndex++] = a;
1060
- triangles[triIndex++] = b;
1061
- triangles[triIndex++] = c;
1062
- }
1063
- }
1064
- processTriangle(0, 0, max, max, max, 0);
1065
- processTriangle(max, max, 0, 0, 0, max);
1066
- if (withSkirts) {
1067
- leftSkirtIndices.sort((a, b) => { return vertices[2 * a + 1] - vertices[2 * b + 1]; });
1068
- rightSkirtIndices.sort((a, b) => { return vertices[2 * b + 1] - vertices[2 * a + 1]; });
1069
- bottomSkirtIndices.sort((a, b) => { return vertices[2 * b] - vertices[2 * a]; });
1070
- topSkirtIndices.sort((a, b) => { return vertices[2 * a] - vertices[2 * b]; });
1071
- let skirtIndex = numVertices * 2;
1072
- function constructSkirt(skirt) {
1073
- const skirtLength = skirt.length;
1074
- for (let i = 0; i < skirtLength - 1; i++) {
1075
- const currIndex = skirt[i];
1076
- const nextIndex = skirt[i + 1];
1077
- const currentSkirt = skirtIndex / 2;
1078
- const nextSkirt = (skirtIndex + 2) / 2;
1079
- vertices[skirtIndex++] = vertices[2 * currIndex];
1080
- vertices[skirtIndex++] = vertices[2 * currIndex + 1];
1081
- triangles[triIndex++] = currIndex;
1082
- triangles[triIndex++] = currentSkirt;
1083
- triangles[triIndex++] = nextIndex;
1084
- triangles[triIndex++] = currentSkirt;
1085
- triangles[triIndex++] = nextSkirt;
1086
- triangles[triIndex++] = nextIndex;
1087
- }
1088
- vertices[skirtIndex++] = vertices[2 * skirt[skirtLength - 1]];
1089
- vertices[skirtIndex++] = vertices[2 * skirt[skirtLength - 1] + 1];
1090
- }
1091
- constructSkirt(leftSkirtIndices);
1092
- constructSkirt(rightSkirtIndices);
1093
- constructSkirt(bottomSkirtIndices);
1094
- constructSkirt(topSkirtIndices);
1095
- }
1096
- return { vertices: vertices, triangles: triangles, numVerticesWithoutSkirts: numVertices };
1097
- }
1098
- }
1099
-
1100
- class MapMartiniHeightNode extends MapHeightNode {
1101
- constructor(parentNode = null, mapView = null, location = QuadTreePosition.root, level = 0, x = 0, y = 0, { elevationDecoder = null, meshMaxError = 10, exageration = 1 } = {}) {
1102
- super(parentNode, mapView, location, level, x, y, MapMartiniHeightNode.geometry, MapMartiniHeightNode.prepareMaterial(new MeshPhongMaterial({
1103
- map: MapMartiniHeightNode.emptyTexture,
1104
- color: 0xFFFFFF,
1105
- side: DoubleSide
1106
- }), level, exageration));
1107
- this.elevationDecoder = {
1108
- rScaler: 256,
1109
- gScaler: 1,
1110
- bScaler: 1 / 256,
1111
- offset: -32768
1112
- };
1113
- this.exageration = 1.0;
1114
- this.meshMaxError = 10;
1115
- if (elevationDecoder) {
1116
- this.elevationDecoder = elevationDecoder;
1117
- }
1118
- this.meshMaxError = meshMaxError;
1119
- this.exageration = exageration;
1120
- this.frustumCulled = false;
1121
- }
1122
- static prepareMaterial(material, level, exageration = 1.0) {
1123
- material.userData = {
1124
- heightMap: { value: MapMartiniHeightNode.emptyTexture },
1125
- drawNormals: { value: 0 },
1126
- drawBlack: { value: 0 },
1127
- zoomlevel: { value: level },
1128
- computeNormals: { value: 1 },
1129
- drawTexture: { value: 1 }
1130
- };
1131
- material.onBeforeCompile = (shader) => {
1132
- for (let i in material.userData) {
1133
- shader.uniforms[i] = material.userData[i];
1134
- }
1135
- shader.vertexShader =
1136
- `
1137
- uniform bool computeNormals;
1138
- uniform float zoomlevel;
1139
- uniform sampler2D heightMap;
1140
- ` + shader.vertexShader;
1141
- shader.fragmentShader =
1142
- `
1143
- uniform bool drawNormals;
1144
- uniform bool drawTexture;
1145
- uniform bool drawBlack;
1146
- ` + shader.fragmentShader;
1147
- shader.fragmentShader = shader.fragmentShader.replace('#include <dithering_fragment>', `
1148
- if(drawBlack) {
1149
- gl_FragColor = vec4( 0.0,0.0,0.0, 1.0 );
1150
- } else if(drawNormals) {
1151
- gl_FragColor = vec4( ( 0.5 * vNormal + 0.5 ), 1.0 );
1152
- } else if (!drawTexture) {
1153
- gl_FragColor = vec4( 0.0,0.0,0.0, 0.0 );
1154
- }`);
1155
- shader.vertexShader = shader.vertexShader.replace('#include <fog_vertex>', `
1156
- #include <fog_vertex>
1157
-
1158
- // queried pixels:
1159
- // +-----------+
1160
- // | | | |
1161
- // | a | b | c |
1162
- // | | | |
1163
- // +-----------+
1164
- // | | | |
1165
- // | d | e | f |
1166
- // | | | |
1167
- // +-----------+
1168
- // | | | |
1169
- // | g | h | i |
1170
- // | | | |
1171
- // +-----------+
1172
-
1173
- if (computeNormals) {
1174
- float e = getElevation(vUv, 0.0);
1175
- ivec2 size = textureSize(heightMap, 0);
1176
- float offset = 1.0 / float(size.x);
1177
- float a = getElevation(vUv + vec2(-offset, -offset), 0.0);
1178
- float b = getElevation(vUv + vec2(0, -offset), 0.0);
1179
- float c = getElevation(vUv + vec2(offset, -offset), 0.0);
1180
- float d = getElevation(vUv + vec2(-offset, 0), 0.0);
1181
- float f = getElevation(vUv + vec2(offset, 0), 0.0);
1182
- float g = getElevation(vUv + vec2(-offset, offset), 0.0);
1183
- float h = getElevation(vUv + vec2(0, offset), 0.0);
1184
- float i = getElevation(vUv + vec2(offset,offset), 0.0);
1185
-
1186
-
1187
- float normalLength = 500.0 / zoomlevel;
1188
-
1189
- vec3 v0 = vec3(0.0, 0.0, 0.0);
1190
- vec3 v1 = vec3(0.0, normalLength, 0.0);
1191
- vec3 v2 = vec3(normalLength, 0.0, 0.0);
1192
- v0.z = (e + d + g + h) / 4.0;
1193
- v1.z = (e+ b + a + d) / 4.0;
1194
- v2.z = (e+ h + i + f) / 4.0;
1195
- vNormal = (normalize(cross(v2 - v0, v1 - v0))).rbg;
1196
- }
1197
- `);
1198
- };
1199
- return material;
1200
- }
1201
- static getTerrain(imageData, tileSize, elevation) {
1202
- const { rScaler, bScaler, gScaler, offset } = elevation;
1203
- const gridSize = tileSize + 1;
1204
- const terrain = new Float32Array(gridSize * gridSize);
1205
- for (let i = 0, y = 0; y < tileSize; y++) {
1206
- for (let x = 0; x < tileSize; x++, i++) {
1207
- const k = i * 4;
1208
- const r = imageData[k + 0];
1209
- const g = imageData[k + 1];
1210
- const b = imageData[k + 2];
1211
- terrain[i + y] = r * rScaler + g * gScaler + b * bScaler + offset;
1212
- }
1213
- }
1214
- for (let i = gridSize * (gridSize - 1), x = 0; x < gridSize - 1; x++, i++) {
1215
- terrain[i] = terrain[i - gridSize];
1216
- }
1217
- for (let i = gridSize - 1, y = 0; y < gridSize; y++, i += gridSize) {
1218
- terrain[i] = terrain[i - 1];
1219
- }
1220
- return terrain;
1221
- }
1222
- static getMeshAttributes(vertices, terrain, tileSize, bounds, exageration) {
1223
- const gridSize = tileSize + 1;
1224
- const numOfVerticies = vertices.length / 2;
1225
- const positions = new Float32Array(numOfVerticies * 3);
1226
- const texCoords = new Float32Array(numOfVerticies * 2);
1227
- const [minX, minY, maxX, maxY] = bounds || [0, 0, tileSize, tileSize];
1228
- const xScale = (maxX - minX) / tileSize;
1229
- const yScale = (maxY - minY) / tileSize;
1230
- for (let i = 0; i < numOfVerticies; i++) {
1231
- const x = vertices[i * 2];
1232
- const y = vertices[i * 2 + 1];
1233
- const pixelIdx = y * gridSize + x;
1234
- positions[3 * i + 0] = x * xScale + minX;
1235
- positions[3 * i + 1] = -terrain[pixelIdx] * exageration;
1236
- positions[3 * i + 2] = -y * yScale + maxY;
1237
- texCoords[2 * i + 0] = x / tileSize;
1238
- texCoords[2 * i + 1] = y / tileSize;
1239
- }
1240
- return {
1241
- position: { value: positions, size: 3 },
1242
- uv: { value: texCoords, size: 2 }
1243
- };
1244
- }
1245
- processHeight(image) {
1246
- return __awaiter(this, void 0, void 0, function* () {
1247
- const tileSize = image.width;
1248
- const gridSize = tileSize + 1;
1249
- var canvas = CanvasUtils.createOffscreenCanvas(tileSize, tileSize);
1250
- var context = canvas.getContext('2d');
1251
- context.imageSmoothingEnabled = false;
1252
- context.drawImage(image, 0, 0, tileSize, tileSize, 0, 0, canvas.width, canvas.height);
1253
- var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
1254
- var data = imageData.data;
1255
- const terrain = MapMartiniHeightNode.getTerrain(data, tileSize, this.elevationDecoder);
1256
- const martini = new Martini(gridSize);
1257
- const tile = martini.createTile(terrain);
1258
- const { vertices, triangles } = tile.getMesh(typeof this.meshMaxError === 'function' ? this.meshMaxError(this.level) : this.meshMaxError);
1259
- const attributes = MapMartiniHeightNode.getMeshAttributes(vertices, terrain, tileSize, [-0.5, -0.5, 0.5, 0.5], this.exageration);
1260
- this.geometry = new BufferGeometry();
1261
- this.geometry.setIndex(new Uint32BufferAttribute(triangles, 1));
1262
- this.geometry.setAttribute('position', new Float32BufferAttribute(attributes.position.value, attributes.position.size));
1263
- this.geometry.setAttribute('uv', new Float32BufferAttribute(attributes.uv.value, attributes.uv.size));
1264
- this.geometry.rotateX(Math.PI);
1265
- var texture = new Texture(image);
1266
- texture.generateMipmaps = false;
1267
- texture.format = RGBAFormat;
1268
- texture.magFilter = NearestFilter;
1269
- texture.minFilter = NearestFilter;
1270
- texture.needsUpdate = true;
1271
- this.material.userData.heightMap.value = texture;
1272
- this.material.map = texture;
1273
- this.material.needsUpdate = true;
1274
- });
1275
- }
1276
- loadHeightGeometry() {
1277
- return __awaiter(this, void 0, void 0, function* () {
1278
- if (this.mapView.heightProvider === null) {
1279
- throw new Error('GeoThree: MapView.heightProvider provider is null.');
1280
- }
1281
- const image = yield this.mapView.heightProvider.fetchTile(this.level, this.x, this.y);
1282
- if (this.disposed) {
1283
- return;
1284
- }
1285
- this.processHeight(image);
1286
- this.heightLoaded = true;
1287
- this.nodeReady();
1288
- });
1289
- }
1290
- }
1291
- MapMartiniHeightNode.geometrySize = 16;
1292
- MapMartiniHeightNode.emptyTexture = new Texture();
1293
- MapMartiniHeightNode.geometry = new MapNodeGeometry(1, 1, 1, 1);
1294
- MapMartiniHeightNode.tileSize = 256;
1295
-
1296
- class MapView extends Mesh {
1297
- constructor(root = MapView.PLANAR, provider = new OpenStreetMapsProvider(), heightProvider = null) {
1298
- super(undefined, new MeshBasicMaterial({ transparent: true, opacity: 0.0 }));
1299
- this.lod = null;
1300
- this.provider = null;
1301
- this.heightProvider = null;
1302
- this.root = null;
1303
- this.cacheTiles = false;
1304
- this.onBeforeRender = (renderer, scene, camera, geometry, material, group) => {
1305
- this.lod.updateLOD(this, camera, renderer, scene);
1306
- };
1307
- this.lod = new LODRaycast();
1308
- this.provider = provider;
1309
- this.heightProvider = heightProvider;
1310
- this.setRoot(root);
1311
- this.preSubdivide();
1312
- }
1313
- setRoot(root) {
1314
- if (typeof root === 'number') {
1315
- if (!MapView.mapModes.has(root)) {
1316
- throw new Error('Map mode ' + root + ' does is not registered.');
1317
- }
1318
- const rootConstructor = MapView.mapModes.get(root);
1319
- root = new rootConstructor(null, this);
1320
- }
1321
- if (this.root !== null) {
1322
- this.remove(this.root);
1323
- this.root = null;
1324
- }
1325
- this.root = root;
1326
- if (this.root !== null) {
1327
- this.geometry = this.root.constructor.baseGeometry;
1328
- this.scale.copy(this.root.constructor.baseScale);
1329
- this.root.mapView = this;
1330
- this.add(this.root);
1331
- this.root.initialize();
1332
- }
1333
- }
1334
- preSubdivide() {
1335
- var _a, _b;
1336
- function subdivide(node, depth) {
1337
- if (depth <= 0) {
1338
- return;
1339
- }
1340
- node.subdivide();
1341
- for (let i = 0; i < node.children.length; i++) {
1342
- if (node.children[i] instanceof MapNode) {
1343
- const child = node.children[i];
1344
- subdivide(child, depth - 1);
1345
- }
1346
- }
1347
- }
1348
- const minZoom = Math.max(this.provider.minZoom, (_b = (_a = this.heightProvider) === null || _a === void 0 ? void 0 : _a.minZoom) !== null && _b !== void 0 ? _b : -Infinity);
1349
- if (minZoom > 0) {
1350
- subdivide(this.root, minZoom);
1351
- }
1352
- }
1353
- setProvider(provider) {
1354
- if (provider !== this.provider) {
1355
- this.provider = provider;
1356
- this.clear();
1357
- }
1358
- }
1359
- setHeightProvider(heightProvider) {
1360
- if (heightProvider !== this.heightProvider) {
1361
- this.heightProvider = heightProvider;
1362
- this.clear();
1363
- }
1364
- }
1365
- clear() {
1366
- this.traverse(function (children) {
1367
- if (children.childrenCache) {
1368
- children.childrenCache = null;
1369
- }
1370
- if (children.initialize) {
1371
- children.initialize();
1372
- }
1373
- });
1374
- return this;
1375
- }
1376
- minZoom() {
1377
- var _a, _b;
1378
- return Math.max(this.provider.minZoom, (_b = (_a = this.heightProvider) === null || _a === void 0 ? void 0 : _a.minZoom) !== null && _b !== void 0 ? _b : -Infinity);
1379
- }
1380
- maxZoom() {
1381
- var _a, _b;
1382
- return Math.min(this.provider.maxZoom, (_b = (_a = this.heightProvider) === null || _a === void 0 ? void 0 : _a.maxZoom) !== null && _b !== void 0 ? _b : Infinity);
1383
- }
1384
- getMetaData() {
1385
- this.provider.getMetaData();
1386
- }
1387
- raycast(raycaster, intersects) {
1388
- return false;
1389
- }
1390
- }
1391
- MapView.PLANAR = 200;
1392
- MapView.SPHERICAL = 201;
1393
- MapView.HEIGHT = 202;
1394
- MapView.HEIGHT_SHADER = 203;
1395
- MapView.MARTINI = 204;
1396
- MapView.mapModes = new Map([
1397
- [MapView.PLANAR, MapPlaneNode],
1398
- [MapView.SPHERICAL, MapSphereNode],
1399
- [MapView.HEIGHT, MapHeightNode],
1400
- [MapView.HEIGHT_SHADER, MapHeightNodeShader],
1401
- [MapView.MARTINI, MapMartiniHeightNode]
1402
- ]);
1403
-
1404
- const pov$1 = new Vector3();
1405
- const position$1 = new Vector3();
1406
- class LODRadial {
1407
- constructor(subdivideDistance = 50, simplifyDistance = 300) {
1408
- this.subdivideDistance = subdivideDistance;
1409
- this.simplifyDistance = simplifyDistance;
1410
- }
1411
- updateLOD(view, camera, renderer, scene) {
1412
- camera.getWorldPosition(pov$1);
1413
- view.children[0].traverse((node) => {
1414
- node.getWorldPosition(position$1);
1415
- let distance = pov$1.distanceTo(position$1);
1416
- distance /= Math.pow(2, view.provider.maxZoom - node.level);
1417
- if (distance < this.subdivideDistance) {
1418
- node.subdivide();
1419
- }
1420
- else if (distance > this.simplifyDistance && node.parentNode) {
1421
- node.parentNode.simplify();
1422
- }
1423
- });
1424
- }
1425
- }
1426
-
1427
- const projection = new Matrix4();
1428
- const pov = new Vector3();
1429
- const frustum = new Frustum();
1430
- const position = new Vector3();
1431
- class LODFrustum extends LODRadial {
1432
- constructor(subdivideDistance = 120, simplifyDistance = 400) {
1433
- super(subdivideDistance, simplifyDistance);
1434
- this.testCenter = true;
1435
- this.pointOnly = false;
1436
- }
1437
- updateLOD(view, camera, renderer, scene) {
1438
- projection.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
1439
- frustum.setFromProjectionMatrix(projection);
1440
- camera.getWorldPosition(pov);
1441
- view.children[0].traverse((node) => {
1442
- node.getWorldPosition(position);
1443
- let distance = pov.distanceTo(position);
1444
- distance /= Math.pow(2, view.provider.maxZoom - node.level);
1445
- const inFrustum = this.pointOnly ? frustum.containsPoint(position) : frustum.intersectsObject(node);
1446
- if (distance < this.subdivideDistance && inFrustum) {
1447
- node.subdivide();
1448
- }
1449
- else if (distance > this.simplifyDistance && node.parentNode) {
1450
- node.parentNode.simplify();
1451
- }
1452
- });
1453
- }
1454
- }
1455
-
1456
- class XHRUtils {
1457
- static get(url) {
1458
- return __awaiter(this, void 0, void 0, function* () {
1459
- return new Promise(function (resolve, reject) {
1460
- const xhr = new XMLHttpRequest();
1461
- xhr.overrideMimeType('text/plain');
1462
- xhr.open('GET', url, true);
1463
- xhr.onload = function () {
1464
- resolve(xhr.response);
1465
- };
1466
- xhr.onerror = reject;
1467
- xhr.send(null);
1468
- });
1469
- });
1470
- }
1471
- static getRaw(url) {
1472
- return __awaiter(this, void 0, void 0, function* () {
1473
- return new Promise(function (resolve, reject) {
1474
- var xhr = new XMLHttpRequest();
1475
- xhr.responseType = 'arraybuffer';
1476
- xhr.open('GET', url, true);
1477
- xhr.onload = function () {
1478
- resolve(xhr.response);
1479
- };
1480
- xhr.onerror = reject;
1481
- xhr.send(null);
1482
- });
1483
- });
1484
- }
1485
- static request(url, type, header, body, onLoad, onError, onProgress) {
1486
- function parseResponse(response) {
1487
- try {
1488
- return JSON.parse(response);
1489
- }
1490
- catch (e) {
1491
- return response;
1492
- }
1493
- }
1494
- const xhr = new XMLHttpRequest();
1495
- xhr.overrideMimeType('text/plain');
1496
- xhr.open(type, url, true);
1497
- if (header !== null && header !== undefined) {
1498
- for (const i in header) {
1499
- xhr.setRequestHeader(i, header[i]);
1500
- }
1501
- }
1502
- if (onLoad !== undefined) {
1503
- xhr.onload = function (event) {
1504
- onLoad(parseResponse(xhr.response), xhr);
1505
- };
1506
- }
1507
- if (onError !== undefined) {
1508
- xhr.onerror = onError;
1509
- }
1510
- if (onProgress !== undefined) {
1511
- xhr.onprogress = onProgress;
1512
- }
1513
- xhr.send(body !== undefined ? body : null);
1514
- return xhr;
1515
- }
1516
- }
1517
-
1518
- class BingMapsProvider extends MapProvider {
1519
- constructor(apiKey = '', type = BingMapsProvider.AERIAL) {
1520
- super();
1521
- this.maxZoom = 19;
1522
- this.minZoom = 1;
1523
- this.format = 'jpeg';
1524
- this.mapSize = 512;
1525
- this.subdomain = 't1';
1526
- this.meta = null;
1527
- this.apiKey = apiKey;
1528
- this.type = type;
1529
- }
1530
- getMetaData() {
1531
- return __awaiter(this, void 0, void 0, function* () {
1532
- const address = BingMapsProvider.ADDRESS + '/REST/V1/Imagery/Metadata/RoadOnDemand?output=json&include=ImageryProviders&key=' + this.apiKey;
1533
- const data = yield XHRUtils.get(address);
1534
- this.meta = JSON.parse(data);
1535
- });
1536
- }
1537
- static quadKey(zoom, x, y) {
1538
- let quad = '';
1539
- for (let i = zoom; i > 0; i--) {
1540
- const mask = 1 << i - 1;
1541
- let cell = 0;
1542
- if ((x & mask) !== 0) {
1543
- cell++;
1544
- }
1545
- if ((y & mask) !== 0) {
1546
- cell += 2;
1547
- }
1548
- quad += cell;
1549
- }
1550
- return quad;
1551
- }
1552
- fetchTile(zoom, x, y) {
1553
- return new Promise((resolve, reject) => {
1554
- const image = document.createElement('img');
1555
- image.onload = function () {
1556
- resolve(image);
1557
- };
1558
- image.onerror = function () {
1559
- reject();
1560
- };
1561
- image.crossOrigin = 'Anonymous';
1562
- image.src = 'http://ecn.' + this.subdomain + '.tiles.virtualearth.net/tiles/' + this.type + BingMapsProvider.quadKey(zoom, x, y) + '.jpeg?g=1173';
1563
- });
1564
- }
1565
- }
1566
- BingMapsProvider.ADDRESS = 'https://dev.virtualearth.net';
1567
- BingMapsProvider.AERIAL = 'a';
1568
- BingMapsProvider.ROAD = 'r';
1569
- BingMapsProvider.AERIAL_LABELS = 'h';
1570
- BingMapsProvider.OBLIQUE = 'o';
1571
- BingMapsProvider.OBLIQUE_LABELS = 'b';
1572
-
1573
- class GoogleMapsProvider extends MapProvider {
1574
- constructor(apiToken) {
1575
- super();
1576
- this.sessionToken = null;
1577
- this.orientation = 0;
1578
- this.format = 'png';
1579
- this.mapType = 'roadmap';
1580
- this.overlay = false;
1581
- this.apiToken = apiToken !== undefined ? apiToken : '';
1582
- this.createSession();
1583
- }
1584
- createSession() {
1585
- const address = 'https://www.googleapis.com/tile/v1/createSession?key=' + this.apiToken;
1586
- const data = JSON.stringify({
1587
- mapType: this.mapType,
1588
- language: 'en-EN',
1589
- region: 'en',
1590
- layerTypes: ['layerRoadmap', 'layerStreetview'],
1591
- overlay: this.overlay,
1592
- scale: 'scaleFactor1x'
1593
- });
1594
- XHRUtils.request(address, 'GET', { 'Content-Type': 'text/json' }, data, (response, xhr) => {
1595
- this.sessionToken = response.session;
1596
- }, function (xhr) {
1597
- throw new Error('Unable to create a google maps session.');
1598
- });
1599
- }
1600
- fetchTile(zoom, x, y) {
1601
- return new Promise((resolve, reject) => {
1602
- const image = document.createElement('img');
1603
- image.onload = function () {
1604
- resolve(image);
1605
- };
1606
- image.onerror = function () {
1607
- reject();
1608
- };
1609
- image.crossOrigin = 'Anonymous';
1610
- image.src = 'https://www.googleapis.com/tile/v1/tiles/' + zoom + '/' + x + '/' + y + '?session=' + this.sessionToken + '&orientation=' + this.orientation + '&key=' + this.apiToken;
1611
- });
1612
- }
1613
- }
1614
-
1615
- class HereMapsProvider extends MapProvider {
1616
- constructor(appId = '', appCode = '', style = 'base', scheme = 'normal.day', format = 'png', size = 512) {
1617
- super();
1618
- this.appId = appId;
1619
- this.appCode = appCode;
1620
- this.style = style;
1621
- this.scheme = scheme;
1622
- this.format = format;
1623
- this.size = size;
1624
- this.version = 'newest';
1625
- this.server = 1;
1626
- }
1627
- nextServer() {
1628
- this.server = this.server % 4 === 0 ? 1 : this.server + 1;
1629
- }
1630
- getMetaData() {
1631
- return __awaiter(this, void 0, void 0, function* () { });
1632
- }
1633
- fetchTile(zoom, x, y) {
1634
- this.nextServer();
1635
- return new Promise((resolve, reject) => {
1636
- const image = document.createElement('img');
1637
- image.onload = function () {
1638
- resolve(image);
1639
- };
1640
- image.onerror = function () {
1641
- reject();
1642
- };
1643
- image.crossOrigin = 'Anonymous';
1644
- image.src = 'https://' + this.server + '.' + this.style + '.maps.api.here.com/maptile/2.1/maptile/' +
1645
- this.version + '/' + this.scheme + '/' + zoom + '/' + x + '/' + y + '/' +
1646
- this.size + '/' + this.format + '?app_id=' + this.appId + '&app_code=' + this.appCode;
1647
- });
1648
- }
1649
- }
1650
- HereMapsProvider.PATH = '/maptile/2.1/';
1651
-
1652
- class MapBoxProvider extends MapProvider {
1653
- constructor(apiToken = '', id = '', mode = MapBoxProvider.STYLE, format = 'png', useHDPI = false, version = 'v4') {
1654
- super();
1655
- this.apiToken = apiToken;
1656
- this.format = format;
1657
- this.useHDPI = useHDPI;
1658
- this.mode = mode;
1659
- this.mapId = id;
1660
- this.style = id;
1661
- this.version = version;
1662
- }
1663
- getMetaData() {
1664
- return __awaiter(this, void 0, void 0, function* () {
1665
- const address = MapBoxProvider.ADDRESS + this.version + '/' + this.mapId + '.json?access_token=' + this.apiToken;
1666
- const data = yield XHRUtils.get(address);
1667
- const meta = JSON.parse(data);
1668
- this.name = meta.name;
1669
- this.minZoom = meta.minZoom;
1670
- this.maxZoom = meta.maxZoom;
1671
- this.bounds = meta.bounds;
1672
- this.center = meta.center;
1673
- });
1674
- }
1675
- fetchTile(zoom, x, y) {
1676
- return new Promise((resolve, reject) => {
1677
- const image = document.createElement('img');
1678
- image.onload = function () {
1679
- resolve(image);
1680
- };
1681
- image.onerror = function () {
1682
- reject();
1683
- };
1684
- image.crossOrigin = 'Anonymous';
1685
- if (this.mode === MapBoxProvider.STYLE) {
1686
- image.src = MapBoxProvider.ADDRESS + 'styles/v1/' + this.style + '/tiles/' + zoom + '/' + x + '/' + y + (this.useHDPI ? '@2x?access_token=' : '?access_token=') + this.apiToken;
1687
- }
1688
- else {
1689
- image.src = MapBoxProvider.ADDRESS + 'v4/' + this.mapId + '/' + zoom + '/' + x + '/' + y + (this.useHDPI ? '@2x.' : '.') + this.format + '?access_token=' + this.apiToken;
1690
- }
1691
- });
1692
- }
1693
- }
1694
- MapBoxProvider.ADDRESS = 'https://api.mapbox.com/';
1695
- MapBoxProvider.STYLE = 100;
1696
- MapBoxProvider.MAP_ID = 101;
1697
-
1698
- class MapTilerProvider extends MapProvider {
1699
- constructor(apiKey, category, style, format) {
1700
- super();
1701
- this.apiKey = apiKey !== undefined ? apiKey : '';
1702
- this.format = format !== undefined ? format : 'png';
1703
- this.category = category !== undefined ? category : 'maps';
1704
- this.style = style !== undefined ? style : 'satellite';
1705
- this.resolution = 512;
1706
- }
1707
- fetchTile(zoom, x, y) {
1708
- return new Promise((resolve, reject) => {
1709
- const image = document.createElement('img');
1710
- image.onload = function () {
1711
- resolve(image);
1712
- };
1713
- image.onerror = function () {
1714
- reject();
1715
- };
1716
- image.crossOrigin = 'Anonymous';
1717
- image.src = 'https://api.maptiler.com/' + this.category + '/' + this.style + '/' + zoom + '/' + x + '/' + y + '.' + this.format + '?key=' + this.apiKey;
1718
- });
1719
- }
1720
- }
1721
-
1722
- class OpenMapTilesProvider extends MapProvider {
1723
- constructor(address, format = 'png', theme = 'klokantech-basic') {
1724
- super();
1725
- this.address = address;
1726
- this.format = format;
1727
- this.theme = theme;
1728
- }
1729
- getMetaData() {
1730
- return __awaiter(this, void 0, void 0, function* () {
1731
- const address = this.address + 'styles/' + this.theme + '.json';
1732
- const data = yield XHRUtils.get(address);
1733
- const meta = JSON.parse(data);
1734
- this.name = meta.name;
1735
- this.format = meta.format;
1736
- this.minZoom = meta.minZoom;
1737
- this.maxZoom = meta.maxZoom;
1738
- this.bounds = meta.bounds;
1739
- this.center = meta.center;
1740
- });
1741
- }
1742
- fetchTile(zoom, x, y) {
1743
- return new Promise((resolve, reject) => {
1744
- const image = document.createElement('img');
1745
- image.onload = function () {
1746
- resolve(image);
1747
- };
1748
- image.onerror = function () {
1749
- reject();
1750
- };
1751
- image.crossOrigin = 'Anonymous';
1752
- image.src = this.address + 'styles/' + this.theme + '/' + zoom + '/' + x + '/' + y + '.' + this.format;
1753
- });
1754
- }
1755
- }
1756
-
1757
- class DebugProvider extends MapProvider {
1758
- constructor() {
1759
- super(...arguments);
1760
- this.resolution = 256;
1761
- }
1762
- fetchTile(zoom, x, y) {
1763
- const canvas = CanvasUtils.createOffscreenCanvas(this.resolution, this.resolution);
1764
- const context = canvas.getContext('2d');
1765
- const green = new Color(0x00ff00);
1766
- const red = new Color(0xff0000);
1767
- const color = green.lerpHSL(red, (zoom - this.minZoom) / (this.maxZoom - this.minZoom));
1768
- context.fillStyle = color.getStyle();
1769
- context.fillRect(0, 0, this.resolution, this.resolution);
1770
- context.fillStyle = '#000000';
1771
- context.textAlign = 'center';
1772
- context.textBaseline = 'middle';
1773
- context.font = 'bold ' + this.resolution * 0.1 + 'px arial';
1774
- context.fillText('(' + zoom + ')', this.resolution / 2, this.resolution * 0.4);
1775
- context.fillText('(' + x + ', ' + y + ')', this.resolution / 2, this.resolution * 0.6);
1776
- return Promise.resolve(canvas);
1777
- }
1778
- }
1779
-
1780
- class HeightDebugProvider extends MapProvider {
1781
- constructor(provider) {
1782
- super();
1783
- this.fromColor = new Color(0xff0000);
1784
- this.toColor = new Color(0x00ff00);
1785
- this.provider = provider;
1786
- }
1787
- fetchTile(zoom, x, y) {
1788
- return __awaiter(this, void 0, void 0, function* () {
1789
- const image = yield this.provider.fetchTile(zoom, x, y);
1790
- const resolution = 256;
1791
- const canvas = CanvasUtils.createOffscreenCanvas(resolution, resolution);
1792
- const context = canvas.getContext('2d');
1793
- context.drawImage(image, 0, 0, resolution, resolution, 0, 0, resolution, resolution);
1794
- const imageData = context.getImageData(0, 0, resolution, resolution);
1795
- const data = imageData.data;
1796
- for (let i = 0; i < data.length; i += 4) {
1797
- const r = data[i];
1798
- const g = data[i + 1];
1799
- const b = data[i + 2];
1800
- const value = (r * 65536 + g * 256 + b) * 0.1 - 1e4;
1801
- const max = 1667721.6;
1802
- const color = this.fromColor.clone().lerpHSL(this.toColor, value / max);
1803
- data[i] = color.r * 255;
1804
- data[i + 1] = color.g * 255;
1805
- data[i + 2] = color.b * 255;
1806
- }
1807
- context.putImageData(imageData, 0, 0);
1808
- return canvas;
1809
- });
1810
- }
1811
- }
1812
-
1813
- class GeolocationUtils {
1814
- static get() {
1815
- return new Promise(function (resolve, reject) {
1816
- navigator.geolocation.getCurrentPosition(function (result) {
1817
- resolve(result);
1818
- }, reject);
1819
- });
1820
- }
1821
- }
1822
-
1823
- class CancelablePromise {
1824
- constructor(executor) {
1825
- this.fulfilled = false;
1826
- this.rejected = false;
1827
- this.called = false;
1828
- const resolve = (v) => {
1829
- this.fulfilled = true;
1830
- this.value = v;
1831
- if (typeof this.onResolve === 'function') {
1832
- this.onResolve(this.value);
1833
- this.called = true;
1834
- }
1835
- };
1836
- const reject = (reason) => {
1837
- this.rejected = true;
1838
- this.value = reason;
1839
- if (typeof this.onReject === 'function') {
1840
- this.onReject(this.value);
1841
- this.called = true;
1842
- }
1843
- };
1844
- try {
1845
- executor(resolve, reject);
1846
- }
1847
- catch (error) {
1848
- reject(error);
1849
- }
1850
- }
1851
- cancel() {
1852
- return false;
1853
- }
1854
- then(callback) {
1855
- this.onResolve = callback;
1856
- if (this.fulfilled && !this.called) {
1857
- this.called = true;
1858
- this.onResolve(this.value);
1859
- }
1860
- return this;
1861
- }
1862
- catch(callback) {
1863
- this.onReject = callback;
1864
- if (this.rejected && !this.called) {
1865
- this.called = true;
1866
- this.onReject(this.value);
1867
- }
1868
- return this;
1869
- }
1870
- finally(callback) {
1871
- return this;
1872
- }
1873
- static resolve(val) {
1874
- return new CancelablePromise(function executor(resolve, _reject) {
1875
- resolve(val);
1876
- });
1877
- }
1878
- static reject(reason) {
1879
- return new CancelablePromise(function executor(resolve, reject) {
1880
- reject(reason);
1881
- });
1882
- }
1883
- static all(promises) {
1884
- const fulfilledPromises = [];
1885
- const result = [];
1886
- function executor(resolve, reject) {
1887
- promises.forEach((promise, index) => {
1888
- return promise
1889
- .then((val) => {
1890
- fulfilledPromises.push(true);
1891
- result[index] = val;
1892
- if (fulfilledPromises.length === promises.length) {
1893
- return resolve(result);
1894
- }
1895
- })
1896
- .catch((error) => { return reject(error); });
1897
- });
1898
- }
1899
- return new CancelablePromise(executor);
1900
- }
1901
- }
1902
-
1903
- export { BingMapsProvider, CancelablePromise, CanvasUtils, DebugProvider, Geolocation, GeolocationUtils, GoogleMapsProvider, HeightDebugProvider, HereMapsProvider, LODFrustum, LODRadial, LODRaycast, MapBoxProvider, MapHeightNode, MapHeightNodeShader, MapNode, MapNodeGeometry, MapNodeHeightGeometry, MapPlaneNode, MapProvider, MapSphereNode, MapSphereNodeGeometry, MapTilerProvider, MapView, OpenMapTilesProvider, OpenStreetMapsProvider, TextureUtils, UnitsUtils, XHRUtils };