@openglobus/og 0.10.3 → 0.10.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,157 @@
1
+ /**
2
+ * @module og/layer/KML
3
+ */
4
+
5
+ 'use strict';
6
+ import { Entity } from '../entity/Entity.js';
7
+ import { Extent } from '../Extent.js';
8
+ import { LonLat } from '../LonLat.js';
9
+ import { Vector } from './Vector.js';
10
+
11
+ /**
12
+ * Layer to render KMLs files
13
+ * @class
14
+ * @extends {og.Vector}
15
+ */
16
+ export class KML extends Vector {
17
+
18
+ _billboard = { src: 'https://openglobus.org/examples/billboards/carrot.png' };
19
+ _color = '#6689db';
20
+
21
+ constructor(name, options = {}) {
22
+ super(name, options);
23
+ this._extent = null;
24
+ this._billboard = options.billboard || this._billboard;
25
+ this._color = options.color || this._color;
26
+ }
27
+
28
+ get instanceName() {
29
+ return 'KML';
30
+ }
31
+
32
+ /**
33
+ * @private
34
+ */
35
+ _extractCoordonatesFromKml(xmlDoc) {
36
+ const raw = Array.from(xmlDoc.getElementsByTagName('coordinates'));
37
+ const coordinates = raw.map(item => item.textContent.trim().replace(/\n/g, ' ').split(' ').map(co => co.split(',').map(parseFloat)));
38
+ return coordinates;
39
+ }
40
+
41
+ /**
42
+ * Creates billboards or polylines from array of lonlat.
43
+ * @private
44
+ * @param {Array} coordonates
45
+ * @param {string} color
46
+ * @returns {Array<og.Entity>}
47
+ */
48
+ _convertCoordonatesIntoEntities(coordinates, color, billboard) {
49
+ const extent = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
50
+ const addToExtent = (c) => {
51
+ const lon = c[0], lat = c[1];
52
+ if (lon < extent.southWest.lon) extent.southWest.lon = lon;
53
+ if (lat < extent.southWest.lat) extent.southWest.lat = lat;
54
+ if (lon > extent.northEast.lon) extent.northEast.lon = lon;
55
+ if (lat > extent.northEast.lat) extent.northEast.lat = lat;
56
+ };
57
+ const _pathes = [];
58
+ coordinates.forEach(kmlFile => kmlFile.forEach(p => _pathes.push(p)));
59
+ const entities = _pathes.map(path => {
60
+ if (path.length === 1) {
61
+ const lonlat = path[0];
62
+ const _entity = new Entity({ lonlat, billboard });
63
+ addToExtent(lonlat);
64
+ return _entity;
65
+ } else if (path.length > 1) {
66
+ const pathLonLat = path.map(item => {
67
+ addToExtent(item);
68
+ return new LonLat(item[0], item[1], item[2]);
69
+ });
70
+ const _entity = new Entity({ polyline: { pathLonLat: [pathLonLat], thickness: 3, color, isClosed: false } });
71
+ return _entity;
72
+ }
73
+ });
74
+ return { entities, extent };
75
+ }
76
+
77
+ /**
78
+ * @private
79
+ */
80
+ _getXmlContent(file) {
81
+ return new Promise(resolve => {
82
+ const fileReader = new FileReader();
83
+ fileReader.onload = async i => resolve((new DOMParser()).parseFromString(i.target.result, 'text/xml'));
84
+ fileReader.readAsText(file);
85
+ });
86
+ };
87
+
88
+ /**
89
+ * @private
90
+ */
91
+ _expandExtents(extent1, extent2) {
92
+ if (!extent1) return extent2;
93
+ if (extent2.southWest.lon < extent1.southWest.lon) extent1.southWest.lon = extent2.southWest.lon;
94
+ if (extent2.southWest.lat < extent1.southWest.lat) extent1.southWest.lat = extent2.southWest.lat;
95
+ if (extent2.northEast.lon > extent1.northEast.lon) extent1.northEast.lon = extent2.northEast.lon;
96
+ if (extent2.northEast.lat > extent1.northEast.lat) extent1.northEast.lat = extent2.northEast.lat;
97
+ return extent1;
98
+ }
99
+
100
+ /**
101
+ * @public
102
+ * @param {File[]} kmls
103
+ * @returns {Promise}
104
+ */
105
+ async addKmlFromFiles(kmls) {
106
+ const kmlObjs = await Promise.all(kmls.map(this._getXmlContent));
107
+ const coordonates = kmlObjs.map(this._extractCoordonatesFromKml);
108
+ const { entities, extent } = this._convertCoordonatesIntoEntities(coordonates, this._color, this._billboard);
109
+ this._extent = this._expandExtents(this._extent, extent);
110
+ entities.forEach(this.add.bind(this));
111
+ return { entities, extent };
112
+ }
113
+
114
+ /**
115
+ * @param {string} color
116
+ * @public
117
+ */
118
+ setColor(color) {
119
+ this._color = color;
120
+ this._billboard.color = color;
121
+ }
122
+
123
+ /**
124
+ * @private
125
+ */
126
+ _getKmlFromUrl(url) {
127
+ return new Promise((resolve, reject) => {
128
+ const request = new XMLHttpRequest();
129
+ request.open('GET', url, true);
130
+ request.responseType = 'document';
131
+ request.overrideMimeType('text/xml');
132
+ request.onload = () => {
133
+ if (request.readyState === request.DONE && request.status === 200) {
134
+ resolve(request.responseXML);
135
+ } else {
136
+ reject(new Error('no valid kml file'));
137
+ }
138
+ };
139
+ request.send();
140
+ });
141
+ };
142
+
143
+ /**
144
+ * @public
145
+ * @param {string} url - Url of the KML to display. './myFile.kml' or 'http://mySite/myFile.kml' for example.
146
+ * @returns {Promise}
147
+ */
148
+ async addKmlFromUrl(url) {
149
+ const kml = await this._getKmlFromUrl(url);
150
+ const coordonates = this._extractCoordonatesFromKml(kml);
151
+ const { entities, extent } = this._convertCoordonatesIntoEntities([coordonates], this._color, this._billboard);
152
+ this._extent = this._expandExtents(this._extent, extent);
153
+ entities.forEach(this.add.bind(this));
154
+ return { entities, extent };
155
+ }
156
+
157
+ };
@@ -32,8 +32,7 @@ import {
32
32
 
33
33
  import { MAX_NORMAL_ZOOM } from "../segment/Segment.js";
34
34
 
35
- const DOT_VIS = 0.3;
36
- const VISIBLE_HEIGHT = 3000000.0;
35
+ const VISIBLE_HEIGHT = 1400000.0;
37
36
 
38
37
  let _tempHigh = new Vec3(),
39
38
  _tempLow = new Vec3();
@@ -255,7 +254,7 @@ Node.prototype.renderTree = function (cam, maxZoom, terrainReadySegment, stopLoa
255
254
  }
256
255
  }
257
256
  } else {
258
- let commonFrustumFlag = 1 << (numFrustums - 1 - 1); //Math.pow(2, numFrustums - 1) - 1;
257
+ let commonFrustumFlag = 1 << (numFrustums - 1 - 1);
259
258
  for (let i = 0; commonFrustumFlag && i < numFrustums; i++) {
260
259
  if (seg.terrainReady) {
261
260
  if (frustums[i].containsBox(seg.bbox)) {
@@ -332,13 +331,13 @@ Node.prototype.prepareForRendering = function (
332
331
  } else {
333
332
  if (seg.tileZoom < 2) {
334
333
  this.renderNode(inFrustum, !inFrustum, terrainReadySegment, stopLoading);
335
- } else if (seg.tileZoom >= MAX_NORMAL_ZOOM) {
334
+ } else if (seg.tileZoom > MAX_NORMAL_ZOOM) {
336
335
  this.renderNode(inFrustum, !inFrustum, terrainReadySegment, stopLoading);
337
336
  } else if (
338
- seg._swNorm.dot(cam.eyeNorm) > DOT_VIS ||
339
- seg._nwNorm.dot(cam.eyeNorm) > DOT_VIS ||
340
- seg._neNorm.dot(cam.eyeNorm) > DOT_VIS ||
341
- seg._seNorm.dot(cam.eyeNorm) > DOT_VIS
337
+ seg._swNorm.dot(cam._n) > 0.0 ||
338
+ seg._nwNorm.dot(cam._n) > 0.0 ||
339
+ seg._neNorm.dot(cam._n) > 0.0 ||
340
+ seg._seNorm.dot(cam._n) > 0.0
342
341
  ) {
343
342
  this.renderNode(inFrustum, !inFrustum, terrainReadySegment, stopLoading);
344
343
  } else {
@@ -478,26 +477,80 @@ Node.prototype.getCommonSide = function (node) {
478
477
  b_sw_lon = b_sw.lon,
479
478
  b_sw_lat = b_sw.lat;
480
479
 
480
+ if (as._tileGroup === bs._tileGroup) {
481
+ if (
482
+ a_ne_lon === b_sw_lon &&
483
+ ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
484
+ (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
485
+ ) {
486
+ return E;
487
+ } else if (
488
+ a_sw_lon === b_ne_lon &&
489
+ ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
490
+ (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
491
+ ) {
492
+ return W;
493
+ } else if (
494
+ a_ne_lat === b_sw_lat &&
495
+ ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
496
+ (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
497
+ ) {
498
+ return N;
499
+ } else if (
500
+ a_sw_lat === b_ne_lat &&
501
+ ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
502
+ (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
503
+ ) {
504
+ return S;
505
+ } else if (
506
+ bs.tileX === 0 &&
507
+ as.tileX === Math.pow(2, as.tileZoom) - 1 &&
508
+ ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
509
+ (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
510
+ ) {
511
+ return E;
512
+ } else if (
513
+ as.tileX === 0 &&
514
+ bs.tileX === Math.pow(2, bs.tileZoom) - 1 &&
515
+ ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
516
+ (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
517
+ ) {
518
+ return W;
519
+ }
520
+ }
521
+
481
522
  if (
482
- a_ne_lon === b_sw_lon &&
483
- ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
484
- (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
523
+ as._tileGroup === 0 &&
524
+ bs._tileGroup === 1 &&
525
+ as.tileY === 0 &&
526
+ bs.tileY === Math.pow(2, bs.tileZoom) - 1 &&
527
+ ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
528
+ (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
485
529
  ) {
486
- return E;
530
+ return N;
487
531
  } else if (
488
- a_sw_lon === b_ne_lon &&
489
- ((a_ne_lat <= b_ne_lat && a_sw_lat >= b_sw_lat) ||
490
- (a_ne_lat >= b_ne_lat && a_sw_lat <= b_sw_lat))
532
+ as._tileGroup === 2 &&
533
+ bs._tileGroup === 0 &&
534
+ as.tileY === 0 &&
535
+ bs.tileY === Math.pow(2, bs.tileZoom) - 1 &&
536
+ ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
537
+ (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
491
538
  ) {
492
- return W;
539
+ return N;
493
540
  } else if (
494
- a_ne_lat === b_sw_lat &&
541
+ bs._tileGroup === 1 &&
542
+ as._tileGroup === 0 &&
543
+ as.tileY === Math.pow(2, as.tileZoom) - 1 &&
544
+ bs.tileY === 0 &&
495
545
  ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
496
546
  (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
497
547
  ) {
498
- return N;
548
+ return S;
499
549
  } else if (
500
- a_sw_lat === b_ne_lat &&
550
+ as._tileGroup === 1 &&
551
+ bs._tileGroup === 0 &&
552
+ as.tileY === Math.pow(2, as.tileZoom) - 1 &&
553
+ bs.tileY === 0 &&
501
554
  ((a_sw_lon >= b_sw_lon && a_ne_lon <= b_ne_lon) ||
502
555
  (a_sw_lon <= b_sw_lon && a_ne_lon >= b_ne_lon))
503
556
  ) {
@@ -301,33 +301,38 @@ class RendererEvents extends Events {
301
301
  }
302
302
 
303
303
  /**
304
- * @private
304
+ * @protected
305
305
  */
306
- onMouseMove(event, sys) {
307
- let b = sys.buttons;
308
-
309
- if (b & LB_M) {
310
- this.mouseState.leftButtonDown = true;
306
+ updateButtonsStates(buttons) {
307
+ var ms = this.mouseState;
308
+ if (buttons & LB_M) {
309
+ ms.leftButtonDown = true;
311
310
  } else {
312
- this.mouseState.leftButtonHold = false;
313
- this.mouseState.leftButtonDown = false;
311
+ ms.leftButtonHold = false;
312
+ ms.leftButtonDown = false;
314
313
  }
315
314
 
316
- if (b & RB_M) {
317
- this.mouseState.rightButtonDown = true;
315
+ if (buttons & RB_M) {
316
+ ms.rightButtonDown = true;
318
317
  } else {
319
- this.mouseState.rightButtonHold = false;
320
- this.mouseState.rightButtonDown = false;
318
+ ms.rightButtonHold = false;
319
+ ms.rightButtonDown = false;
321
320
  }
322
321
 
323
- if (b & MB_M) {
324
- this.mouseState.middleButtonDown = true;
322
+ if (buttons & MB_M) {
323
+ ms.middleButtonDown = true;
325
324
  } else {
326
- this.mouseState.middleButtonHold = false;
327
- this.mouseState.middleButtonDown = false;
325
+ ms.middleButtonHold = false;
326
+ ms.middleButtonDown = false;
328
327
  }
328
+ }
329
329
 
330
+ /**
331
+ * @private
332
+ */
333
+ onMouseMove(event, sys) {
330
334
  var ms = this.mouseState;
335
+ this.updateButtonsStates(sys.buttons)
331
336
  ms.sys = event;
332
337
 
333
338
  let ex = event.clientX,
@@ -24,7 +24,7 @@ import { PlanetCamera } from "../camera/PlanetCamera.js";
24
24
  import { RenderNode } from "./RenderNode.js";
25
25
  import { Segment } from "../segment/Segment.js";
26
26
  import { SegmentLonLat } from "../segment/SegmentLonLat.js";
27
- import { PlainSegmentWorker } from "../segment/PlainSegmentWorker.js";
27
+ import { PlainSegmentWorker } from "../utils/PlainSegmentWorker.js";
28
28
  import { TerrainWorker } from "../utils/TerrainWorker.js";
29
29
  import { VectorTileCreator } from "../utils/VectorTileCreator.js";
30
30
  import { wgs84 } from "../ellipsoid/wgs84.js";
@@ -174,6 +174,9 @@ class Planet extends RenderNode {
174
174
  */
175
175
  this.camera = null;
176
176
 
177
+ this._minAltitude = options.minAltitude;
178
+ this._maxAltitude = options.maxAltitude;
179
+
177
180
  /**
178
181
  * Screen mouse pointer projected to planet cartesian position.
179
182
  * @public
@@ -699,7 +702,9 @@ class Planet extends RenderNode {
699
702
  this.camera = this.renderer.activeCamera = new PlanetCamera(this, {
700
703
  eye: new Vec3(0, 0, 28000000),
701
704
  look: new Vec3(0, 0, 0),
702
- up: new Vec3(0, 1, 0)
705
+ up: new Vec3(0, 1, 0),
706
+ minAltitude: this._minAltitude,
707
+ maxAltitude: this._maxAltitude
703
708
  });
704
709
 
705
710
  this.camera.update();
@@ -31,8 +31,6 @@ var _RenderingSlice = function (p) {
31
31
  };
32
32
  };
33
33
 
34
- //const BSPHERERADIUSEXT = 2;
35
-
36
34
  /**
37
35
  * Planet segment Web Mercator tile class that stored and rendered with quad tree.
38
36
  * @class
@@ -1002,7 +1000,7 @@ Segment.prototype.createBoundsByExtent = function () {
1002
1000
  var coord_ne = ellipsoid.geodeticToCartesian(extent.northEast.lon, extent.northEast.lat);
1003
1001
 
1004
1002
  // check for zoom
1005
- if (this.tileZoom < MAX_NORMAL_ZOOM) {
1003
+ if (this.tileZoom <= MAX_NORMAL_ZOOM) {
1006
1004
  var coord_nw = ellipsoid.geodeticToCartesian(extent.southWest.lon, extent.northEast.lat);
1007
1005
  var coord_se = ellipsoid.geodeticToCartesian(extent.northEast.lon, extent.southWest.lat);
1008
1006
 
@@ -1039,7 +1037,7 @@ Segment.prototype.createBoundsByParent = function () {
1039
1037
  this.bsphere.center.z = pn.segment.bsphere.center.z;
1040
1038
  this.bsphere.radius = pn.segment.bsphere.radius;
1041
1039
 
1042
- if (this.tileZoom < MAX_NORMAL_ZOOM) {
1040
+ if (this.tileZoom <= MAX_NORMAL_ZOOM) {
1043
1041
  let i0 = gridSize * offsetY;
1044
1042
  let j0 = gridSize * offsetX;
1045
1043
 
@@ -188,6 +188,7 @@ class FontAtlas {
188
188
  };
189
189
 
190
190
  img.src = `${srcDir}/${data.pages[0]}`;
191
+ img.crossOrigin = "Anonymous";
191
192
  })
192
193
  .catch(err => {
193
194
  def.reject();