@openglobus/og 0.15.3 → 0.15.5

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 (71) hide show
  1. package/README.md +3 -7
  2. package/css/og.css +24 -15
  3. package/dist/@openglobus/og.css +1 -1
  4. package/dist/@openglobus/og.esm.js +2 -2
  5. package/dist/@openglobus/og.esm.js.map +1 -1
  6. package/dist/@openglobus/og.umd.js +2 -2
  7. package/dist/@openglobus/og.umd.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/og/Globe.js +4 -0
  10. package/src/og/LonLat.js +207 -193
  11. package/src/og/Object3d.js +1 -1
  12. package/src/og/camera/Camera.js +4 -16
  13. package/src/og/camera/PlanetCamera.js +12 -6
  14. package/src/og/control/DebugInfo.js +263 -165
  15. package/src/og/control/KeyboardNavigation.js +153 -169
  16. package/src/og/control/MouseNavigation.js +0 -20
  17. package/src/og/control/RulerSwitcher.js +4 -1
  18. package/src/og/control/SimpleNavigation.js +123 -128
  19. package/src/og/control/heightRuler/HeightRuler.js +12 -0
  20. package/src/og/control/heightRuler/HeightRulerScene.js +224 -0
  21. package/src/og/control/heightRuler/HeightRulerSwitcher.js +15 -0
  22. package/src/og/control/index.js +2 -0
  23. package/src/og/control/ruler/RulerScene.js +106 -79
  24. package/src/og/ellipsoid/Ellipsoid.js +20 -3
  25. package/src/og/entity/Entity.js +6 -6
  26. package/src/og/entity/EntityCollection.js +4 -0
  27. package/src/og/entity/GeoObjectHandler.js +3 -0
  28. package/src/og/layer/BaseGeoImage.js +152 -16
  29. package/src/og/layer/GeoImage.js +0 -91
  30. package/src/og/layer/GeoTexture2d.js +54 -143
  31. package/src/og/layer/GeoVideo.js +6 -107
  32. package/src/og/layer/Material.js +1 -1
  33. package/src/og/layer/Vector.js +8 -6
  34. package/src/og/layer/XYZ.js +2 -2
  35. package/src/og/quadTree/EntityCollectionNode.js +8 -2
  36. package/src/og/renderer/Renderer.js +91 -94
  37. package/src/og/renderer/RendererEvents.js +39 -23
  38. package/src/og/scene/BaseNode.js +113 -113
  39. package/src/og/scene/Planet.js +20 -13
  40. package/src/og/scene/RenderNode.js +42 -9
  41. package/src/og/segment/Segment.js +38 -45
  42. package/src/og/shaders/geoObject.js +12 -10
  43. package/src/og/shaders/pickingMask.js +1 -1
  44. package/src/og/utils/GeoImageCreator.js +61 -21
  45. package/src/og/utils/VectorTileCreator.js +32 -49
  46. package/src/og/webgl/Framebuffer.js +5 -0
  47. package/types/LonLat.d.ts +8 -0
  48. package/types/camera/PlanetCamera.d.ts +1 -1
  49. package/types/control/DebugInfo.d.ts +4 -0
  50. package/types/control/SimpleNavigation.d.ts +1 -0
  51. package/types/control/heightRuler/HeightRuler.d.ts +6 -0
  52. package/types/control/heightRuler/HeightRulerScene.d.ts +23 -0
  53. package/types/control/index.d.ts +2 -1
  54. package/types/control/ruler/RulerScene.d.ts +8 -5
  55. package/types/control/selection/SelectionScene.d.ts +0 -1
  56. package/types/ellipsoid/Ellipsoid.d.ts +13 -1
  57. package/types/entity/EntityCollection.d.ts +1 -0
  58. package/types/layer/BaseGeoImage.d.ts +17 -3
  59. package/types/layer/GeoImage.d.ts +0 -8
  60. package/types/layer/GeoTexture2d.d.ts +0 -2
  61. package/types/layer/GeoVideo.d.ts +0 -8
  62. package/types/layer/XYZ.d.ts +1 -1
  63. package/types/renderer/Renderer.d.ts +12 -3
  64. package/types/scene/Axes.d.ts +1 -1
  65. package/types/scene/BaseNode.d.ts +2 -2
  66. package/types/scene/Planet.d.ts +0 -5
  67. package/types/scene/RenderNode.d.ts +16 -9
  68. package/types/scene/SkyBox.d.ts +1 -1
  69. package/types/segment/Segment.d.ts +2 -3
  70. package/types/utils/VectorTileCreator.d.ts +1 -3
  71. package/types/webgl/Framebuffer.d.ts +1 -0
@@ -0,0 +1,224 @@
1
+ 'use strict';
2
+
3
+ import { Entity } from '../../entity/Entity.js';
4
+ import { RulerScene } from "../ruler/RulerScene.js";
5
+ import { Vector } from "../../layer/Vector.js";
6
+ import { Object3d } from "../../Object3d.js";
7
+
8
+ let obj3d = Object3d.createCylinder(1.1, 0, 2, 6, 1, true, true, 0, 0, 0)
9
+
10
+ const RAYS_OPTIONS = {
11
+ startColor: "rgb(255,131,0)",
12
+ endColor: "rgb(255,131,0)",
13
+ thickness: 5
14
+ }
15
+ const LABEL_OPTIONS = {
16
+ text: "",
17
+ size: 11,
18
+ color: "rgba(455,455,455,1.0)",
19
+ outlineColor: "rgba(0,0,0,0.34)",
20
+ outline: 0.23,
21
+ align: "center",
22
+ offset: [0, 18]
23
+ };
24
+
25
+ const RULER_CORNER_OPTIONS = {
26
+ scale: 1,
27
+ instanced: true,
28
+ tag: "height-ruler",
29
+ color: "rgb(255,131,0)",
30
+ object3d: obj3d
31
+ };
32
+
33
+ class HeightRulerScene extends RulerScene {
34
+ constructor(options = {}) {
35
+ super(options);
36
+
37
+
38
+ this._cornersLayer = new Vector("corners", {
39
+ entities: [],
40
+ pickingEnabled: true,
41
+ displayInLayerSwitcher: false,
42
+ scaleByDistance: [100, 4000000, 1.0],
43
+ pickingScale: 2
44
+ });
45
+
46
+
47
+ this._geoRulerLayer = new Vector("rayHeightRuler", {
48
+ entities: [],
49
+ pickingEnabled: false,
50
+ polygonOffsetUnits: -2.0,
51
+ relativeToGround: false,
52
+ displayInLayerSwitcher: false
53
+ });
54
+
55
+ }
56
+
57
+ get deltaLabel() {
58
+ return this._heightLabels[2]
59
+ }
60
+
61
+ get startLabel() {
62
+ return this._heightLabels[0]
63
+ }
64
+
65
+ get endLabel() {
66
+ return this._heightLabels[1]
67
+ }
68
+
69
+ get corners() {
70
+ return this._cornerEntity;
71
+ }
72
+
73
+ get startCorner() {
74
+ return this.corners[0];
75
+ }
76
+
77
+ get endCorner() {
78
+ return this.corners[1];
79
+ }
80
+
81
+ get startCornerLonLat() {
82
+ return this.startCorner.getLonLat();
83
+ }
84
+
85
+ get startCornerHeight() {
86
+ return this.startCornerLonLat.height;
87
+ }
88
+
89
+ get endCornerLonLat() {
90
+ return this.endCorner.getLonLat();
91
+ }
92
+
93
+ get endCornerHeight() {
94
+ return this.endCornerLonLat.height;
95
+ }
96
+
97
+ get maxHeightCornerLonLat() {
98
+ if (this.startCornerHeight <= this.endCornerHeight) {
99
+ return this.endCornerLonLat;
100
+ } else {
101
+ return this.startCornerLonLat;
102
+ }
103
+ }
104
+
105
+ get minHeightCornerLonLat() {
106
+ if (this.startCornerHeight > this.endCornerHeight) {
107
+ return this.endCornerLonLat;
108
+ } else {
109
+ return this.startCornerLonLat;
110
+ }
111
+ }
112
+
113
+ get deltaHeight() {
114
+ return Math.abs(this.startCornerHeight - this.endCornerHeight);
115
+ }
116
+
117
+ _drawLine(startLonLat, endLonLat, startPos) {
118
+
119
+ super._drawLine(startLonLat, endLonLat, startPos);
120
+ this._updateHeightRaysAndLabels();
121
+ }
122
+
123
+ async _updateHeightRaysAndLabels() {
124
+ const middleLonLat = this.minHeightCornerLonLat.clone();
125
+ middleLonLat.height = this.maxHeightCornerLonLat.height;
126
+
127
+ this._rayH.ray.setStartPosition3v(this._planet.ellipsoid.lonLatToCartesian(this.maxHeightCornerLonLat))
128
+ this._rayH.ray.setEndPosition3v(this._planet.ellipsoid.lonLatToCartesian(middleLonLat))
129
+ this._rayV.ray.setStartPosition3v(this._planet.ellipsoid.lonLatToCartesian(this.minHeightCornerLonLat));
130
+ this._rayV.ray.setEndPosition3v(this._planet.ellipsoid.lonLatToCartesian(middleLonLat));
131
+
132
+ middleLonLat.height = this.minHeightCornerLonLat.height + this.deltaHeight / 2;
133
+
134
+ this.deltaLabel.setLonLat(middleLonLat);
135
+ this.startLabel.setLonLat(this.startCornerLonLat);
136
+ this.endLabel.setLonLat(this.endCornerLonLat);
137
+
138
+ const startHeight = await this._planet.getHeightDefault(this.startCornerLonLat),
139
+ endHeight = await this._planet.getHeightDefault(this.endCornerLonLat)
140
+
141
+ this.deltaLabel.label.setText(`\u0394 ${Math.abs(startHeight - endHeight).toFixed(1)} m`);
142
+ this.startLabel.label.setText(`P1 ${startHeight.toFixed(1)} m`)
143
+ this.endLabel.label.setText(`P2 ${endHeight.toFixed(1)} m`)
144
+ }
145
+
146
+ clear() {
147
+ this._rayH.remove();
148
+ this._rayV.remove();
149
+ this.startCorner.remove();
150
+ this.endCorner.remove();
151
+ this.startLabel.remove();
152
+ this.endLabel.remove();
153
+ this.deltaLabel.remove();
154
+ super.clear()
155
+ this._rayH = undefined;
156
+ this._rayV = undefined;
157
+
158
+ this._planet.removeLayer(this._geoRulerLayer);
159
+ }
160
+
161
+ _createCorners() {
162
+ this._cornerEntity = [
163
+ new Entity({
164
+ geoObject: RULER_CORNER_OPTIONS,
165
+ properties: {
166
+ name: "start"
167
+ }
168
+ }),
169
+ new Entity({
170
+ geoObject: RULER_CORNER_OPTIONS,
171
+ properties: {
172
+ name: "end"
173
+ }
174
+ })
175
+ ];
176
+ this._cornersLayer.addEntities(this._cornerEntity)
177
+ }
178
+
179
+ init() {
180
+
181
+ super.init();
182
+ this._createCorners();
183
+ this._rayV = new Entity({
184
+ 'name': 'verticalRay',
185
+ 'ray': RAYS_OPTIONS
186
+ });
187
+ this._rayH = new Entity({
188
+ 'name': 'heightRay',
189
+ 'ray': RAYS_OPTIONS
190
+ });
191
+ this._heightLabels = [
192
+ new Entity({
193
+ 'name': 'startCornerLabel',
194
+ 'label': {
195
+ ...LABEL_OPTIONS
196
+ }
197
+ }),
198
+ new Entity({
199
+ 'name': 'endCornerLabel',
200
+ 'label': {
201
+ ...LABEL_OPTIONS
202
+ }
203
+ }),
204
+ new Entity({
205
+ 'name': 'deltaLabel',
206
+ 'label': {
207
+ ...LABEL_OPTIONS
208
+ }
209
+ })
210
+ ];
211
+ this._labelLayer.addEntities(this._heightLabels);
212
+ this._geoRulerLayer.addEntities([this._rayH, this._rayV]);
213
+
214
+ this._planet.addLayer(this._geoRulerLayer);
215
+ }
216
+
217
+ frame() {
218
+ super.frame()
219
+ this._updateHeightRaysAndLabels();
220
+ }
221
+ }
222
+
223
+
224
+ export { HeightRulerScene };
@@ -0,0 +1,15 @@
1
+ import { RulerSwitcher } from "../RulerSwitcher.js";
2
+ import { HeightRuler } from "./HeightRuler.js";
3
+
4
+ export class HeightRulerSwitcher extends RulerSwitcher {
5
+ constructor(options = {}) {
6
+ super({
7
+ name: `HeightRulerSwitcher`,
8
+ ...options
9
+ });
10
+ this.ruler = new HeightRuler({
11
+ ignoreTerrain: options.ignoreTerrain
12
+ });
13
+ }
14
+
15
+ }
@@ -11,6 +11,7 @@ import { Lighting } from "./Lighting.js";
11
11
  import { MouseNavigation } from "./MouseNavigation.js";
12
12
  import { MouseWheelZoomControl } from "./MouseWheelZoomControl.js";
13
13
  import { Ruler } from "./ruler/Ruler.js";
14
+ import { HeightRuler } from "./heightRuler/HeightRuler.js";
14
15
  import { ScaleControl } from "./ScaleControl.js";
15
16
  import { Selection } from "./selection/Selection.js";
16
17
  import { ShowFps } from "./ShowFps.js";
@@ -41,6 +42,7 @@ export {
41
42
  MouseWheelZoomControl,
42
43
  Lighting,
43
44
  Ruler,
45
+ HeightRuler,
44
46
  SimpleSkyBackground,
45
47
  Selection,
46
48
  LayerAnimation
@@ -10,7 +10,7 @@ import { RenderNode } from '../../scene/RenderNode.js';
10
10
 
11
11
  const OUTLINE_COUNT = 120;
12
12
 
13
- function distanceFormat(v) {
13
+ export function distanceFormat(v) {
14
14
  if (v > 1000) {
15
15
  return `${(v / 1000).toFixed(1)} km`;
16
16
  } else if (v > 9) {
@@ -19,6 +19,24 @@ function distanceFormat(v) {
19
19
  return `${v.toFixed(1)} m`;
20
20
  }
21
21
  }
22
+ let obj3d = Object3d.createCylinder(1.1, 0, 2.7, 20, 1, true, false, 0, 0, 0)
23
+
24
+ const LABEL_OPTIONS = {
25
+ text: "",
26
+ size: 11,
27
+ color: "rgba(455,455,455,1.0)",
28
+ outlineColor: "rgba(0,0,0,0.34)",
29
+ outline: 0.23,
30
+ align: "center",
31
+ offset: [0, 20]
32
+ };
33
+ const RULER_CORNER_OPTIONS = {
34
+ scale: 1,
35
+ instanced: true,
36
+ tag: "ruler",
37
+ color: "rgb(0,305,0)",
38
+ object3d: obj3d
39
+ };
22
40
 
23
41
  class RulerScene extends RenderNode {
24
42
  constructor(options = {}) {
@@ -40,71 +58,23 @@ class RulerScene extends RenderNode {
40
58
 
41
59
  this._heading = 0;
42
60
 
43
- this._propsLabel = new Entity({
44
- 'name': 'propsLabel',
45
- 'label': {
46
- text: "",
47
- size: 11,
48
- color: "rgba(455,455,455,1.0)",
49
- outlineColor: "rgba(0,0,0,0.34)",
50
- outline: 0.23,
51
- align: "center",
52
- offset: [0, 18]
53
- }
54
- });
55
-
56
- this._propsLabel.label.setVisibility(false);
57
-
58
- this._trackEntity = new Entity({
59
- polyline: {
60
- path3v: [],
61
- thickness: 4.8,
62
- color: "rgb(255,131,0)",
63
- isClosed: false
64
- }
65
- });
66
-
67
- this._trackEntity.polyline.altitude = 0.01;
68
-
69
- let obj3d = Object3d.createCylinder(1.1, 0, 2.7, 20, 1, true, false, 0, 0, 0)
70
-
71
- this._cornerEntity = [
72
- new Entity({
73
- geoObject: {
74
- scale: 1,
75
- instanced: true,
76
- tag: "ruler",
77
- color: "rgb(0,305,0)",
78
- object3d: obj3d
79
- },
80
- properties: {
81
- name: "start"
82
- }
83
- }),
84
- new Entity({
85
- geoObject: {
86
- scale: 1,
87
- instanced: true,
88
- tag: "ruler",
89
- color: "rgb(455,0,0)",
90
- object3d: obj3d
91
- },
92
- properties: {
93
- name: "end"
94
- }
95
- })
96
- ];
97
-
98
61
  this._trackLayer = new Vector("track", {
99
- entities: [this._trackEntity, this._propsLabel],
62
+ entities: [],
100
63
  pickingEnabled: false,
101
64
  polygonOffsetUnits: -1.0,
102
65
  relativeToGround: true,
103
66
  displayInLayerSwitcher: false
104
67
  });
68
+ this._labelLayer = new Vector("ruler-label", {
69
+ entities: [],
70
+ pickingEnabled: false,
71
+ polygonOffsetUnits: -100.0,
72
+ relativeToGround: true,
73
+ displayInLayerSwitcher: false
74
+ });
105
75
 
106
76
  this._cornersLayer = new Vector("corners", {
107
- entities: [this._cornerEntity[0], this._cornerEntity[1]],
77
+ entities: [],
108
78
  pickingEnabled: true,
109
79
  displayInLayerSwitcher: false,
110
80
  scaleByDistance: [100, 4000000, 1.0],
@@ -123,7 +93,50 @@ class RulerScene extends RenderNode {
123
93
  this._planet = planet;
124
94
  }
125
95
 
96
+ _createCorners() {
97
+ this._cornerEntity = [
98
+ new Entity({
99
+ geoObject: RULER_CORNER_OPTIONS,
100
+ properties: {
101
+ name: "start"
102
+ }
103
+ }),
104
+ new Entity({
105
+ geoObject: RULER_CORNER_OPTIONS,
106
+ properties: {
107
+ name: "end"
108
+ }
109
+ })
110
+ ];
111
+ this._cornersLayer.addEntities(this._cornerEntity)
112
+ }
113
+
126
114
  init() {
115
+
116
+ this._propsLabel = new Entity({
117
+ 'name': 'propsLabel',
118
+ 'label': LABEL_OPTIONS
119
+ });
120
+
121
+ // this._propsLabel.label.setVisibility(false);
122
+
123
+ this._trackEntity = new Entity({
124
+ polyline: {
125
+ path3v: [],
126
+ thickness: 4.8,
127
+ color: "rgb(255,131,0)",
128
+ isClosed: false
129
+ }
130
+ });
131
+
132
+ this._trackEntity.polyline.altitude = 0.01;
133
+
134
+ this._createCorners();
135
+ this._trackLayer.addEntities([this._trackEntity]);
136
+ this._labelLayer.addEntities([ this._propsLabel]);
137
+ this._planet.addLayer(this._labelLayer);
138
+ this._planet.addLayer(this._trackLayer);
139
+ this._planet.addLayer(this._cornersLayer);
127
140
  this._activate();
128
141
  }
129
142
 
@@ -156,8 +169,6 @@ class RulerScene extends RenderNode {
156
169
  this._onCornerLup_ = this._onCornerLup.bind(this);
157
170
  this._cornersLayer.events.on("lup", this._onCornerLup, this);
158
171
 
159
- this._planet.addLayer(this._trackLayer);
160
- this._planet.addLayer(this._cornersLayer);
161
172
 
162
173
  }
163
174
 
@@ -166,8 +177,8 @@ class RulerScene extends RenderNode {
166
177
  this._preventClick = false;
167
178
  this._stopDrawing = false;
168
179
  this._pickedCorner = null;
169
- this._trackLayer.remove();
170
- this._cornersLayer.remove();
180
+ // this._trackLayer.remove();
181
+ // this._cornersLayer.remove();
171
182
 
172
183
  this.renderer.events.off("lclick", this._onLclick_);
173
184
  this.renderer.events.off("mousemove", this._onMouseMove_);
@@ -234,10 +245,10 @@ class RulerScene extends RenderNode {
234
245
  if (!this._preventClick) {
235
246
  if (!this._startLonLat) {
236
247
  this._stopDrawing = false;
237
- this._propsLabel.label.setVisibility(false);
248
+ this._propsLabel.setVisibility(false);
238
249
  this._trackEntity.polyline.setPath3v([]);
239
- this._cornerEntity[0].geoObject.setVisibility(true);
240
- this._cornerEntity[1].geoObject.setVisibility(true);
250
+ this._cornerEntity[0].setVisibility(true);
251
+ this._cornerEntity[1].setVisibility(true);
241
252
  this._startLonLat = startLonLat;
242
253
  } else {
243
254
  this._startLonLat = null;
@@ -302,26 +313,42 @@ class RulerScene extends RenderNode {
302
313
  }
303
314
 
304
315
  clear() {
305
- // удаляем трек
306
- this._trackEntity.polyline.clear();
307
- this._cornerEntity[0].geoObject.setVisibility(false);
308
- this._cornerEntity[1].geoObject.setVisibility(false);
316
+ this._trackEntity.remove();
317
+ this._cornerEntity[0].remove();
318
+ this._cornerEntity[1].remove();
319
+ this._propsLabel.remove();
320
+ this._planet.removeLayer(this._trackLayer);
321
+ this._planet.removeLayer(this._cornersLayer);
309
322
  }
310
323
 
311
- frame() {
324
+ isCornersPositionChanged() {
312
325
  let t = this._trackEntity.polyline.getPath3v()[0];
313
326
  if (t) {
314
- this._cornerEntity[0].setCartesian3v(t[0].clone());
315
- this._cornerEntity[1].setCartesian3v(t[t.length - 1].clone());
327
+ const startPos = t[0].clone(),
328
+ endPos = t[t.length - 1].clone();
329
+ return this._cornerEntity[0].getCartesian().equal(startPos) &&
330
+ this._cornerEntity[1].getCartesian().equal(endPos)
331
+ }
332
+ return false
333
+ }
316
334
 
317
- if (!this._ignoreTerrain) {
318
- let res = 0;
319
- for (let i = 0, len = t.length - 1; i < len; i++) {
320
- res += t[i + 1].distance(t[i]);
335
+ frame() {
336
+ let t = this._trackEntity.polyline.getPath3v()[0];
337
+ if (t) {
338
+ const startPos = t[0].clone(),
339
+ endPos = t[t.length - 1].clone();
340
+
341
+ if (!this.isCornersPositionChanged()) {
342
+ this._cornerEntity[0].setCartesian3v(startPos);
343
+ this._cornerEntity[1].setCartesian3v(endPos);
344
+ if (!this._ignoreTerrain) {
345
+ let res = 0;
346
+ for (let i = 0, len = t.length - 1; i < len; i++) {
347
+ res += t[i + 1].distance(t[i]);
348
+ }
349
+ this._propsLabel.setCartesian3v(t[Math.floor(t.length / 2)]);
350
+ this._propsLabel.label.setText(`${distanceFormat(res)}, ${Math.round(this._heading)} deg`);
321
351
  }
322
-
323
- this._propsLabel.setCartesian3v(t[Math.floor(t.length / 2)]);
324
- this._propsLabel.label.setText(`${distanceFormat(res)}, ${Math.round(this._heading)} deg`);
325
352
  }
326
353
  }
327
354
  }
@@ -409,19 +409,36 @@ class Ellipsoid {
409
409
  return new Vec3(pX * m_X, pY * m_Y, pZ * m_Z);
410
410
  }
411
411
 
412
+ /**
413
+ * Converts 3d cartesian coordinates to geodetic
414
+ * @param {Vec3} cart - Cartesian coordiantes
415
+ * @returns {LonLat} - Geodetic coordinates
416
+ */
412
417
  cartesianToLonLat(cart) {
413
-
414
418
  let p = this.projToSurface(cart);
415
-
416
419
  let n = this.getSurfaceNormal3v(p),
417
420
  h = cart.sub(p);
418
-
419
421
  return new LonLat(
420
422
  Math.atan2(n.x, n.z) * DEGREES,
421
423
  Math.asin(n.y) * DEGREES,
422
424
  Math.sign(h.dot(cart)) * h.length()
423
425
  );
424
426
  }
427
+ /**
428
+ * Converts 3d cartesian coordinates to geodetic
429
+ * @param {Vec3} cart - Cartesian coordiantes
430
+ * @param {LonLat} res - Link geodetic coordinates variable
431
+ * @returns {LonLat} - Geodetic coordinates
432
+ */
433
+ cartesianToLonLatRes(cart, res) {
434
+ let p = this.projToSurface(cart);
435
+ let n = this.getSurfaceNormal3v(p),
436
+ h = cart.sub(p);
437
+ res.lon = Math.atan2(n.x, n.z) * DEGREES;
438
+ res.lat = Math.asin(n.y) * DEGREES;
439
+ res.height = Math.sign(h.dot(cart)) * h.length();
440
+ return res;
441
+ }
425
442
 
426
443
  /**
427
444
  * Gets ellipsoid surface normal.
@@ -531,7 +531,7 @@ class Entity {
531
531
  this.ray = ray;
532
532
  this.ray._entity = this;
533
533
  this.ray.setVisibility(this._visibility);
534
- this._entityCollection && this._entityCollection._rayHandler.add(ray);
534
+ this._entityCollection && this._entityCollection.rayHandler.add(ray);
535
535
  return ray;
536
536
  }
537
537
 
@@ -548,7 +548,7 @@ class Entity {
548
548
  this.polyline = polyline;
549
549
  this.polyline._entity = this;
550
550
  this.polyline.setVisibility(this._visibility);
551
- this._entityCollection && this._entityCollection._polylineHandler.add(polyline);
551
+ this._entityCollection && this._entityCollection.polylineHandler.add(polyline);
552
552
  return polyline;
553
553
  }
554
554
 
@@ -565,7 +565,7 @@ class Entity {
565
565
  this.pointCloud = pointCloud;
566
566
  this.pointCloud._entity = this;
567
567
  this.pointCloud.setVisibility(this._visibility);
568
- this._entityCollection && this._entityCollection._pointCloudHandler.add(pointCloud);
568
+ this._entityCollection && this._entityCollection.pointCloudHandler.add(pointCloud);
569
569
  return pointCloud;
570
570
  }
571
571
 
@@ -600,7 +600,7 @@ class Entity {
600
600
  this.geoObject._entity = this;
601
601
  this.geoObject.setPosition3v(this._cartesian);
602
602
  this.geoObject.setVisibility(this._visibility);
603
- this._entityCollection && this._entityCollection._geoObjectHandler.add(geoObject);
603
+ this._entityCollection && this._entityCollection.geoObjectHandler.add(geoObject);
604
604
  return geoObject;
605
605
  }
606
606
 
@@ -617,7 +617,7 @@ class Entity {
617
617
  this.strip = strip;
618
618
  this.strip._entity = this;
619
619
  this.strip.setVisibility(this._visibility);
620
- this._entityCollection && this._entityCollection._stripHandler.add(strip);
620
+ this._entityCollection && this._entityCollection.stripHandler.add(strip);
621
621
  return strip;
622
622
  }
623
623
 
@@ -644,7 +644,7 @@ class Entity {
644
644
  entity._pickingColor = this._pickingColor;
645
645
  entity.parent = this;
646
646
  this.childrenNodes.push(entity);
647
- this._entityCollection && this._entityCollection._addRecursively(entity);
647
+ this._entityCollection && this._entityCollection.appendChildEntity(entity);
648
648
  }
649
649
 
650
650
  /**
@@ -283,6 +283,10 @@ class EntityCollection {
283
283
  this.scaleByDistance[2] = farInvisible || math.MAX32;
284
284
  }
285
285
 
286
+ appendChildEntity(entity) {
287
+ this._addRecursively(entity);
288
+ }
289
+
286
290
  _addRecursively(entity) {
287
291
  // billboard
288
292
  entity.billboard && this.billboardHandler.add(entity.billboard);
@@ -348,6 +348,8 @@ class GeoObjectHandler {
348
348
  for (let i = 0; i < this._instanceDataMapValues.length; i++) {
349
349
  this._loadDataTagTexture(this._instanceDataMapValues[i]);
350
350
  }
351
+
352
+ this.update();
351
353
  }
352
354
 
353
355
  _addGeoObjectToArray(geoObject) {
@@ -489,6 +491,7 @@ class GeoObjectHandler {
489
491
 
490
492
  drawPicking() {
491
493
  if (this._geoObjects.length && this.pickingEnabled) {
494
+ this.update();
492
495
  this._pickingPASS();
493
496
  }
494
497
  }