@openglobus/og 0.18.4 → 0.19.0

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 (64) hide show
  1. package/README.md +19 -68
  2. package/css/og.css +308 -45
  3. package/lib/@openglobus/og.css +1 -1
  4. package/lib/@openglobus/og.esm.js +1 -1
  5. package/lib/@openglobus/og.esm.js.map +1 -1
  6. package/lib/@openglobus/og.umd.js +1 -1
  7. package/lib/@openglobus/og.umd.js.map +1 -1
  8. package/lib/js/Globe.d.ts +2 -0
  9. package/lib/js/Globe.js +3 -1
  10. package/lib/js/camera/PlanetCamera.d.ts +2 -2
  11. package/lib/js/camera/PlanetCamera.js +3 -2
  12. package/lib/js/control/DebugInfo.js +5 -0
  13. package/lib/js/control/EarthCoordinates.js +2 -2
  14. package/lib/js/control/LayerSwitcher.d.ts +18 -3
  15. package/lib/js/control/LayerSwitcher.js +111 -11
  16. package/lib/js/control/MouseNavigation.d.ts +2 -0
  17. package/lib/js/control/MouseNavigation.js +15 -15
  18. package/lib/js/control/elevationProfile/ElevationProfile.d.ts +41 -25
  19. package/lib/js/control/elevationProfile/ElevationProfile.js +106 -75
  20. package/lib/js/control/elevationProfile/ElevationProfileButtonsView.d.ts +14 -0
  21. package/lib/js/control/elevationProfile/ElevationProfileButtonsView.js +61 -0
  22. package/lib/js/control/elevationProfile/ElevationProfileControl.d.ts +33 -0
  23. package/lib/js/control/elevationProfile/ElevationProfileControl.js +153 -0
  24. package/lib/js/control/elevationProfile/ElevationProfileLegend.d.ts +20 -0
  25. package/lib/js/control/elevationProfile/ElevationProfileLegend.js +82 -0
  26. package/lib/js/control/elevationProfile/ElevationProfileScene.d.ts +80 -0
  27. package/lib/js/control/elevationProfile/ElevationProfileScene.js +539 -0
  28. package/lib/js/control/elevationProfile/ElevationProfileView.d.ts +63 -0
  29. package/lib/js/control/elevationProfile/ElevationProfileView.js +504 -0
  30. package/lib/js/control/elevationProfile/PointListDialog.d.ts +12 -0
  31. package/lib/js/control/elevationProfile/PointListDialog.js +57 -0
  32. package/lib/js/control/heightRuler/HeightRulerScene.js +1 -1
  33. package/lib/js/control/index.d.ts +2 -1
  34. package/lib/js/control/index.js +2 -1
  35. package/lib/js/control/ruler/RulerScene.js +3 -3
  36. package/lib/js/control/selection/SelectionScene.js +2 -2
  37. package/lib/js/entity/Entity.js +5 -1
  38. package/lib/js/entity/Polyline.js +1 -1
  39. package/lib/js/layer/GeoImage.js +3 -0
  40. package/lib/js/layer/Layer.d.ts +18 -4
  41. package/lib/js/layer/Layer.js +25 -4
  42. package/lib/js/layer/XYZ.d.ts +0 -1
  43. package/lib/js/quadTree/Node.d.ts +21 -3
  44. package/lib/js/quadTree/Node.js +173 -62
  45. package/lib/js/renderer/Renderer.d.ts +0 -1
  46. package/lib/js/renderer/Renderer.js +22 -44
  47. package/lib/js/renderer/RendererEvents.d.ts +1 -0
  48. package/lib/js/renderer/RendererEvents.js +5 -7
  49. package/lib/js/scene/Planet.d.ts +33 -4
  50. package/lib/js/scene/Planet.js +206 -84
  51. package/lib/js/segment/Segment.d.ts +7 -1
  52. package/lib/js/segment/Segment.js +40 -12
  53. package/lib/js/shaders/drawnode.js +21 -2
  54. package/lib/js/shaders/geoObject.js +26 -18
  55. package/lib/js/terrain/GlobusTerrain.d.ts +3 -0
  56. package/lib/js/terrain/GlobusTerrain.js +15 -3
  57. package/lib/js/terrain/MapboxTerrain.js +29 -29
  58. package/lib/js/ui/Dialog.js +1 -1
  59. package/lib/js/utils/TerrainWorker.js +1 -1
  60. package/lib/js/utils/shared.d.ts +3 -1
  61. package/lib/js/utils/shared.js +22 -3
  62. package/package.json +2 -2
  63. package/lib/js/shaders/pickingMask.d.ts +0 -2
  64. package/lib/js/shaders/pickingMask.js +0 -22
@@ -1,13 +1,14 @@
1
1
  import { Deferred } from '../../Deferred';
2
2
  import { createEvents } from '../../Events';
3
3
  import { Vec3 } from "../../math/Vec3";
4
- const ELEVATIONPROFILE_EVENTS = ["profilecollected"];
4
+ const DEFAULT_WARNING_HEIGHT_LEVEL = 5;
5
+ const ELEVATIONPROFILE_EVENTS = ["startcollecting", "profilecollected", "clear"];
5
6
  /**
6
7
  * Point types
7
8
  */
8
- const SAFE = 0;
9
- const WARNING = 1;
10
- const COLLISION = 2;
9
+ export const SAFE = 0;
10
+ export const WARNING = 1;
11
+ export const COLLISION = 2;
11
12
  /**
12
13
  * drawData index names
13
14
  */
@@ -16,51 +17,75 @@ const GROUND = 1;
16
17
  const SEGMMENT_LENGTH = 1.0; // Distance between query points on the ground
17
18
  const GROUND_OFFSET = 1.0; // Ground level offset
18
19
  const BOTTOM_PADDING = 0.1; // Range minY padding in percentage from the bottom
19
- const TOP_PADDING = 0.1; // Range maxY padding in percentage from the top
20
+ const TOP_PADDING = 0.2; // Range maxY padding in percentage from the top
20
21
  const HEIGHT_EPS = 0.1; // Warning height level error
21
- class ElevationProfile {
22
- constructor(options) {
22
+ export class ElevationProfile {
23
+ constructor(options = {}) {
23
24
  this.events = createEvents(ELEVATIONPROFILE_EVENTS);
24
- this.planet = options.planet;
25
- this._warningHeightLevel = 50;
25
+ this.planet = options.planet || null;
26
+ this._warningHeightLevel = DEFAULT_WARNING_HEIGHT_LEVEL;
26
27
  this._pointsReady = false;
27
28
  this._isWarning = false;
28
29
  this._minX = 0;
29
- this._maxX = 1000;
30
+ this._planeDistance = this._maxX = 1000;
30
31
  this._minY = 0;
31
32
  this._maxY = 200;
32
- this._drawData = [][0];
33
+ this._drawData = [[], []];
33
34
  this._promiseArr = [];
34
35
  this._promiseCounter = 0;
35
36
  this._pMaxY = 0;
36
37
  this._pMinY = 0;
37
38
  this._pDist = 0;
38
- this._pTrackCoords = [[0, 0, SAFE]];
39
- this._pGroundCoords = [[0, 0, SAFE]];
39
+ this._pTrackCoords = [];
40
+ this._pGroundCoords = [];
40
41
  this._pIndex = 0;
41
42
  }
43
+ bindPlanet(planet) {
44
+ this.planet = planet;
45
+ }
42
46
  setWarningHeightLevel(warningHeight = 0) {
43
47
  this._warningHeightLevel = warningHeight;
44
48
  }
45
49
  setRange(minX, maxX, minY, maxY) {
46
50
  this._minX = minX;
47
51
  this._maxX = maxX;
48
- this._minY = minY;
49
- this._maxY = maxY;
52
+ if (minY) {
53
+ this._minY = minY;
54
+ }
55
+ if (maxY) {
56
+ this._maxY = maxY;
57
+ }
50
58
  }
51
- _getHeightAsync(ll, pIndex) {
59
+ _getHeightAsync(ll, pIndex, promiseCounter) {
52
60
  let def = new Deferred();
53
- this.planet.terrain.getHeightAsync(ll, (elv) => {
54
- elv += this.planet.terrain.geoid.getHeightLonLat(ll);
55
- this._pGroundCoords[pIndex][1] = elv;
56
- this._pGroundCoords[pIndex][2] = SAFE;
57
- this._pGroundCoords[pIndex][3] = ll.height;
58
- this._setPointType(pIndex);
59
- def.resolve(elv);
60
- });
61
+ if (this.planet) {
62
+ let msl = this.planet.terrain.geoid.getHeightLonLat(ll);
63
+ this.planet.terrain.getHeightAsync(ll, (elv) => {
64
+ if (this.planet && promiseCounter === this._promiseCounter) {
65
+ elv += msl;
66
+ this._pGroundCoords[pIndex][1] = elv;
67
+ this._pGroundCoords[pIndex][2] = SAFE;
68
+ this._pGroundCoords[pIndex][3] = ll.height;
69
+ if (elv > this._pMaxY)
70
+ this._pMaxY = elv;
71
+ if (elv < this._pMinY)
72
+ this._pMinY = elv;
73
+ this._updatePointType(pIndex);
74
+ def.resolve(elv);
75
+ }
76
+ else {
77
+ def.reject();
78
+ }
79
+ });
80
+ }
81
+ else {
82
+ def.reject();
83
+ }
61
84
  return def.promise;
62
85
  }
63
- _collectCoordsBetweenTwoTrackPoints(internalPoints, scaleFactor, p0, trackDir) {
86
+ _collectCoordsBetweenTwoTrackPoints(index, internalPoints, scaleFactor, p0, trackDir, promiseCounter) {
87
+ if (!this.planet)
88
+ return;
64
89
  for (let j = 1; j <= internalPoints; j++) {
65
90
  this._pDist += SEGMMENT_LENGTH;
66
91
  this._pIndex++;
@@ -68,19 +93,17 @@ class ElevationProfile {
68
93
  let dirSegLen = j * scaleFactor;
69
94
  let pjd = p0.add(trackDir.scaleTo(dirSegLen));
70
95
  let llx = this.planet.ellipsoid.cartesianToLonLat(pjd);
71
- this._pGroundCoords[this._pIndex] = [this._pDist, 0, SAFE];
96
+ this._pGroundCoords[this._pIndex] = [this._pDist, 0, SAFE, 0, index];
72
97
  ((lonlat, index) => {
73
- this._promiseArr.push(this._getHeightAsync(lonlat, index)
74
- .then((elv) => {
75
- if (elv > this._pMaxY)
76
- this._pMaxY = elv;
77
- if (elv < this._pMinY)
78
- this._pMinY = elv;
79
- }));
98
+ this._promiseArr.push(this._getHeightAsync(lonlat, index, promiseCounter));
80
99
  })(llx, this._pIndex);
81
100
  }
82
101
  }
83
- _collectAllPoints(pointsLonLat) {
102
+ _collectAllPoints(pointsLonLat, promiseCounter) {
103
+ if (!this.planet)
104
+ return;
105
+ if (promiseCounter !== this._promiseCounter)
106
+ return;
84
107
  let p0 = new Vec3(), p1 = new Vec3();
85
108
  for (let i = 1, len = pointsLonLat.length; i < len; i++) {
86
109
  let lonlat0 = pointsLonLat[i - 1], lonlat1 = pointsLonLat[i];
@@ -93,11 +116,11 @@ class ElevationProfile {
93
116
  let projLen = proj.length();
94
117
  let internalPoints = Math.floor(projLen / SEGMMENT_LENGTH);
95
118
  let scaleFactor = SEGMMENT_LENGTH * dirLength / projLen;
96
- this._getGroundElevation(lonlat0);
119
+ this._getGroundElevation(lonlat0, i - 1, promiseCounter);
97
120
  proj.normalize();
98
121
  trackDir.normalize();
99
122
  // Getting internal point elevations and looking for the collisions
100
- this._collectCoordsBetweenTwoTrackPoints(internalPoints, scaleFactor, p0, trackDir);
123
+ this._collectCoordsBetweenTwoTrackPoints(i - 1, internalPoints, scaleFactor, p0, trackDir, promiseCounter);
101
124
  this._pDist += projLen - internalPoints * SEGMMENT_LENGTH;
102
125
  this._pIndex++;
103
126
  let elv = lonlat1.height;
@@ -105,49 +128,41 @@ class ElevationProfile {
105
128
  this._pMaxY = elv;
106
129
  if (elv < this._pMinY)
107
130
  this._pMinY = elv;
108
- this._pTrackCoords[i] = [this._pDist, elv];
131
+ this._pTrackCoords[i] = [this._pDist, elv, this._pIndex];
109
132
  }
110
133
  }
111
- _getGroundElevation(lonLat) {
112
- this._pGroundCoords[this._pIndex] = [this._pDist, 0, SAFE];
113
- this._promiseArr.push(this._getHeightAsync(lonLat, this._pIndex)
114
- .then((elv) => {
115
- if (typeof elv === 'number') {
116
- if ((elv > this._pMaxY) && (elv))
117
- this._pMaxY = elv;
118
- if ((elv < this._pMinY) && (elv))
119
- this._pMinY = elv;
120
- }
121
- }));
122
- }
123
- _collectPromise(resolve) {
124
- Promise.all(this._promiseArr).then(() => {
125
- resolve({
126
- dist: this._pDist,
127
- minY: this._pMinY,
128
- maxY: this._pMaxY,
129
- trackCoords: this._pTrackCoords,
130
- groundCoords: this._pGroundCoords
131
- });
132
- });
134
+ _getGroundElevation(lonLat, index, promiseCounter) {
135
+ this._pGroundCoords[this._pIndex] = [this._pDist, 0, SAFE, 0, index];
136
+ this._promiseArr.push(this._getHeightAsync(lonLat, this._pIndex, promiseCounter));
133
137
  }
134
- _calcPointsAsync(pointsLonLat) {
138
+ _calcPointsAsync(pointsLonLat, promiseCounter) {
135
139
  return new Promise((resolve, reject) => {
136
- this._pTrackCoords = [[0, pointsLonLat[0].height]];
140
+ this._pTrackCoords = [[0, pointsLonLat[0].height, 0]];
137
141
  this._pMaxY = pointsLonLat[0].height;
138
142
  this._pMinY = this._pMaxY;
139
143
  this._pDist = 0;
140
- this._pGroundCoords = [[0, 0, SAFE]];
144
+ this._pGroundCoords = [];
141
145
  this._pIndex = 0;
142
146
  this._promiseArr = [];
143
- this._collectAllPoints(pointsLonLat);
144
- this._getGroundElevation(pointsLonLat[pointsLonLat.length - 1]);
145
- this._collectPromise(resolve);
147
+ this._collectAllPoints(pointsLonLat, promiseCounter);
148
+ this._getGroundElevation(pointsLonLat[pointsLonLat.length - 1], pointsLonLat.length - 1, promiseCounter);
149
+ Promise.all(this._promiseArr).then(() => {
150
+ resolve({
151
+ dist: this._pDist,
152
+ minY: this._pMinY,
153
+ maxY: this._pMaxY,
154
+ trackCoords: this._pTrackCoords,
155
+ groundCoords: this._pGroundCoords
156
+ });
157
+ });
146
158
  });
147
159
  }
148
160
  get minX() {
149
161
  return this._minX;
150
162
  }
163
+ get planeDistance() {
164
+ return this._planeDistance;
165
+ }
151
166
  get maxX() {
152
167
  return this._maxX;
153
168
  }
@@ -163,24 +178,36 @@ class ElevationProfile {
163
178
  get isWarningOrCollision() {
164
179
  return this._isWarning;
165
180
  }
181
+ get drawData() {
182
+ return this._drawData;
183
+ }
166
184
  collectProfile(pointsLonLat) {
185
+ let def = new Deferred();
186
+ if (!this.planet)
187
+ def.reject();
167
188
  this._pointsReady = false;
168
189
  this._isWarning = false;
169
- if (!pointsLonLat || !pointsLonLat.length)
170
- return;
190
+ if (!pointsLonLat || !pointsLonLat.length) {
191
+ def.reject();
192
+ return def.promise;
193
+ }
194
+ this.events.dispatch(this.events.startcollecting, this);
171
195
  this._promiseCounter++;
172
196
  ((counter) => {
173
- this._calcPointsAsync(pointsLonLat).then((p) => {
197
+ this._calcPointsAsync(pointsLonLat, counter).then((p) => {
174
198
  if (counter === this._promiseCounter) {
199
+ this._planeDistance = p.dist;
175
200
  this.setRange(0, p.dist, p.minY - BOTTOM_PADDING * Math.abs(p.minY), p.maxY + Math.abs(p.maxY) * TOP_PADDING);
176
201
  this._pointsReady = true;
177
202
  this._drawData = [p.trackCoords, p.groundCoords];
178
203
  this.events.dispatch(this.events.profilecollected, this._drawData, this);
204
+ def.resolve(this._drawData);
179
205
  }
180
206
  });
181
207
  })(this._promiseCounter);
208
+ return def.promise;
182
209
  }
183
- _setPointType(pIndex) {
210
+ _updatePointType(pIndex) {
184
211
  if ((this._pGroundCoords[pIndex][3] >= this._pGroundCoords[pIndex][1]) &&
185
212
  (this._pGroundCoords[pIndex][3] < this._pGroundCoords[pIndex][1] + this._warningHeightLevel - HEIGHT_EPS)) {
186
213
  this._pGroundCoords[pIndex][2] = WARNING;
@@ -188,30 +215,34 @@ class ElevationProfile {
188
215
  if (this._pGroundCoords[pIndex][3] <= this._pGroundCoords[pIndex][1] + GROUND_OFFSET) {
189
216
  this._pGroundCoords[pIndex][2] = COLLISION;
190
217
  }
191
- if (this._pGroundCoords[pIndex][2] == WARNING || this._pGroundCoords[pIndex][2] == COLLISION) {
218
+ if (this._pGroundCoords[pIndex][2] === WARNING || this._pGroundCoords[pIndex][2] === COLLISION) {
192
219
  this._isWarning = true;
193
220
  }
194
221
  }
222
+ /**
223
+ * @deprecated
224
+ */
195
225
  _setPointsType() {
196
226
  this._isWarning = false;
197
227
  this._pTrackCoords = this._drawData[TRACK];
198
228
  this._pGroundCoords = this._drawData[GROUND];
199
229
  for (let i = 0; i < this._pGroundCoords.length; i++) {
200
- this._setPointType(i);
230
+ this._updatePointType(i);
201
231
  }
202
232
  this._drawData[GROUND] = this._pGroundCoords;
203
233
  this.events.dispatch(this.events.profilecollected, this._drawData, this);
204
234
  }
205
235
  clear() {
236
+ this._promiseCounter = 0;
206
237
  this._pointsReady = false;
207
238
  this._isWarning = false;
208
- this._drawData = [][0];
239
+ this._drawData = [[], []];
209
240
  this._pMaxY = 0;
210
241
  this._pMinY = 0;
211
242
  this._pDist = 0;
212
- this._pTrackCoords = [[0, 0, SAFE]];
213
- this._pGroundCoords = [[0, 0, SAFE]];
243
+ this._pTrackCoords = [];
244
+ this._pGroundCoords = [];
214
245
  this._pIndex = 0;
246
+ this.events.dispatch(this.events.clear, this._drawData, this);
215
247
  }
216
248
  }
217
- export { COLLISION, SAFE, WARNING, ElevationProfile, };
@@ -0,0 +1,14 @@
1
+ import { View, IViewParams, ViewEventsList } from "../../ui/View";
2
+ import { ToggleButton } from "../../ui/ToggleButton";
3
+ import { EventsHandler } from "../../Events";
4
+ import { ElevationProfile } from "./ElevationProfile";
5
+ interface IElevationProfileButtonsViewParams extends IViewParams {
6
+ }
7
+ type ElevationProfileButtonsViewEventsList = ["reset", "list", "location"];
8
+ export declare class ElevationProfileButtonsView extends View<ElevationProfile> {
9
+ events: EventsHandler<ElevationProfileButtonsViewEventsList> & EventsHandler<ViewEventsList>;
10
+ pointListBtn: ToggleButton;
11
+ constructor(params?: IElevationProfileButtonsViewParams);
12
+ render(params: any): this;
13
+ }
14
+ export {};
@@ -0,0 +1,61 @@
1
+ import { View } from "../../ui/View";
2
+ import { Button } from "../../ui/Button";
3
+ import { ToggleButton } from "../../ui/ToggleButton";
4
+ const TEMPLATE = '<div class="og-elevationprofile-buttons"></div>';
5
+ const RESET_SVG_ICON = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
6
+ <svg width="30" height="30" viewBox="0 0 30 30" version="1.1">
7
+ <g transform="translate(0,-289.0625)">
8
+ <path d="M 15 6 C 10.041282 6 6 10.04128 6 15 C 6 19.95872 10.041282 24 15 24 C 16.586491 24 18.07668 23.58246 19.373047 22.857422 L 17.888672 21.375 C 17.00816 21.772814 16.032235 22 15 22 C 11.122162 22 8 18.87784 8 15 C 8 11.12216 11.122162 8 15 8 C 18.877838 8 22 11.12216 22 15 L 19 15 L 23 20 L 27 15 L 24 15 C 24 10.04128 19.958718 6 15 6 z " transform="translate(0,289.0625)" />
9
+ </g>
10
+ </svg>`;
11
+ const LIST_SVG_ICON = `<?xml version="1.0" encoding="utf-8"?><svg width="800px" height="800px" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;}</style></defs><title>list</title><rect x="10" y="6" width="18" height="2"/><rect x="10" y="24" width="18" height="2"/><rect x="10" y="15" width="18" height="2"/><rect x="4" y="15" width="2" height="2"/><rect x="4" y="6" width="2" height="2"/><rect x="4" y="24" width="2" height="2"/></svg>`;
12
+ const LOCATION_SVG_ICON = `<?xml version="1.0" encoding="utf-8"?>
13
+ <!-- Svg Vector Icons : http://www.onlinewebfonts.com/icon -->
14
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
15
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
16
+ <metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
17
+ <g><g><path fill="#000000" d="M127,169.4c23.7,0,42.8-18.3,42.8-41s-19.2-41-42.8-41c-23.7,0-42.8,18.4-42.8,41S103.4,169.4,127,169.4z"/><path fill="#000000" d="M221.7,120.2c-3.8-44-40.9-78.9-87-82V15h-16.3v23.6c-44.8,4-80.3,38.5-84.1,81.7H10v15.6h24.3c3.8,43.1,39.3,77.4,84.1,81.7V241h16.3v-23.2c46-3.1,83.2-37.9,87-82H246v-15.6H221.7L221.7,120.2L221.7,120.2z M128,201.6c-42.5,0-76.7-33-76.7-73.4c0-40.4,34.5-73.4,76.7-73.4c42.5,0,76.7,33,76.7,73.4C204.7,168.5,170.5,201.6,128,201.6L128,201.6z"/></g></g>
18
+ </svg>`;
19
+ const ELEVATIONPROFILEBUTTONSVIEW_EVENTS = ["reset", "list", "location"];
20
+ export class ElevationProfileButtonsView extends View {
21
+ constructor(params = {}) {
22
+ super({
23
+ ...params,
24
+ template: TEMPLATE
25
+ });
26
+ //@ts-ignore
27
+ this.events = this.events.registerNames(ELEVATIONPROFILEBUTTONSVIEW_EVENTS);
28
+ this.pointListBtn = new ToggleButton({
29
+ classList: ["og-elevationprofile-button"],
30
+ icon: LIST_SVG_ICON,
31
+ title: "Point List"
32
+ });
33
+ this.pointListBtn.events.on("change", (isActive) => {
34
+ this.events.dispatch(this.events.list, isActive);
35
+ });
36
+ }
37
+ render(params) {
38
+ super.render(params);
39
+ let resetBtn = new Button({
40
+ classList: ["og-elevationprofile-button"],
41
+ icon: RESET_SVG_ICON,
42
+ title: "Reset"
43
+ });
44
+ resetBtn.appendTo(this.el);
45
+ resetBtn.events.on("click", () => {
46
+ this.model.clear();
47
+ this.events.dispatch(this.events.reset, this);
48
+ });
49
+ this.pointListBtn.appendTo(this.el);
50
+ let locationBtn = new Button({
51
+ classList: ["og-elevationprofile-button", "og-elevationprofile-button__location"],
52
+ icon: LOCATION_SVG_ICON,
53
+ title: "View bounds"
54
+ });
55
+ locationBtn.appendTo(this.el);
56
+ locationBtn.events.on("click", () => {
57
+ this.events.dispatch(this.events.location, this);
58
+ });
59
+ return this;
60
+ }
61
+ }
@@ -0,0 +1,33 @@
1
+ import { Control, IControlParams } from "../Control";
2
+ import { Dialog } from "../../ui/Dialog";
3
+ import { View } from "../../ui/View";
4
+ import { ToggleButton } from "../../ui/ToggleButton";
5
+ import { ElevationProfileView } from "./ElevationProfileView";
6
+ import { ElevationProfileScene } from "./ElevationProfileScene";
7
+ import { ElevationProfileButtonsView } from "./ElevationProfileButtonsView";
8
+ import { PointListDialog } from "./PointListDialog";
9
+ import { GroundItem, TrackItem } from "./ElevationProfile";
10
+ import { ElevationProfileLegend } from "./ElevationProfileLegend";
11
+ interface IElevationProfileGraphParams extends IControlParams {
12
+ }
13
+ export declare class ElevationProfileControl extends Control {
14
+ protected _toggleBtn: ToggleButton;
15
+ protected _dialog: Dialog<null>;
16
+ protected _graphView: View<null>;
17
+ protected _poiListDialog: PointListDialog;
18
+ protected _elevationProfileView: ElevationProfileView;
19
+ protected _elevationProfileScene: ElevationProfileScene;
20
+ protected _elevationProfileButtonsView: ElevationProfileButtonsView;
21
+ protected _elevationProfileLegend: ElevationProfileLegend;
22
+ protected _collectProfileThrottled: () => void;
23
+ constructor(options?: IElevationProfileGraphParams);
24
+ oninit(): void;
25
+ protected _onSceneChange: () => void;
26
+ onactivate(): void;
27
+ ondeactivate(): void;
28
+ protected _onElevationProfilePointer: (pointerDistance: number, tp0: TrackItem, tp1: TrackItem, gp0: GroundItem, gp1: GroundItem, trackPoiIndex: number, groundPoiIndex: number, elevation: number) => void;
29
+ protected _onElevationProfileDblClick: (pointerDistance: number, tp0: TrackItem, tp1: TrackItem, gp0: GroundItem, gp1: GroundItem, trackPoiIndex: number, groundPoiIndex: number, elevation: number) => void;
30
+ protected _onElevationProfileMouseEnter: () => void;
31
+ protected _onElevationProfileMouseLeave: () => void;
32
+ }
33
+ export {};
@@ -0,0 +1,153 @@
1
+ import { Control } from "../Control";
2
+ import { Dialog } from "../../ui/Dialog";
3
+ import { View } from "../../ui/View";
4
+ import { ToggleButton } from "../../ui/ToggleButton";
5
+ import { ElevationProfileView } from "./ElevationProfileView";
6
+ import { ElevationProfileScene } from "./ElevationProfileScene";
7
+ import { throttle } from "../../utils/shared";
8
+ import { ElevationProfileButtonsView } from "./ElevationProfileButtonsView";
9
+ import { PointListDialog } from "./PointListDialog";
10
+ import { ElevationProfileLegend } from "./ElevationProfileLegend";
11
+ const TEMPLATE = `<div class="og-elevationprofile__container">
12
+ <div class="og-elevationprofile__menu"></div>
13
+ <div class="og-elevationprofile__graph"></div>
14
+ </div>`;
15
+ const ICON_BUTTON_SVG = `<svg style="width: 2em; height: 2em;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M128 896v-158.293333l331.946667-191.573334 160.853333 93.866667L896 480V896H128M896 381.44l-275.2 159.146667-160.853333-92.586667L128 640v-94.293333l331.946667-191.573334 160.853333 93.866667L896 288v93.44z" fill="" /></svg>`;
16
+ export class ElevationProfileControl extends Control {
17
+ constructor(options = {}) {
18
+ super({
19
+ name: "ElevationProfileControl",
20
+ ...options
21
+ });
22
+ this._onSceneChange = () => {
23
+ this._collectProfileThrottled();
24
+ };
25
+ this._onElevationProfilePointer = (pointerDistance, tp0, tp1, gp0, gp1, trackPoiIndex, groundPoiIndex, elevation) => {
26
+ let lonLat0 = this._elevationProfileScene.getPointLonLat(trackPoiIndex);
27
+ let lonLat1 = this._elevationProfileScene.getPointLonLat(trackPoiIndex + 1);
28
+ let cart0 = this.planet.ellipsoid.lonLatToCartesian(lonLat0), cart1 = this.planet.ellipsoid.lonLatToCartesian(lonLat1);
29
+ let d = (pointerDistance - tp0[0]) / (tp1[0] - tp0[0]);
30
+ let dir = cart1.sub(cart0);
31
+ this._elevationProfileScene.setPointerCartesian3v(cart0.add(dir.scale(d)), elevation);
32
+ };
33
+ this._onElevationProfileDblClick = (pointerDistance, tp0, tp1, gp0, gp1, trackPoiIndex, groundPoiIndex, elevation) => {
34
+ let lonLat0 = this._elevationProfileScene.getPointLonLat(trackPoiIndex);
35
+ let lonLat1 = this._elevationProfileScene.getPointLonLat(trackPoiIndex + 1);
36
+ let cart0 = this.planet.ellipsoid.lonLatToCartesian(lonLat0), cart1 = this.planet.ellipsoid.lonLatToCartesian(lonLat1);
37
+ let d = (pointerDistance - tp0[0]) / (tp1[0] - tp0[0]);
38
+ let dir = cart1.sub(cart0);
39
+ let poi = cart0.add(dir.scale(d));
40
+ this.planet.camera.flyDistance(poi, this.planet.camera.eye.distance(poi));
41
+ };
42
+ this._onElevationProfileMouseEnter = () => {
43
+ if (this._elevationProfileView.model.pointsReady) {
44
+ this._elevationProfileScene.setPointerVisibility(true);
45
+ }
46
+ };
47
+ this._onElevationProfileMouseLeave = () => {
48
+ };
49
+ this._elevationProfileScene = new ElevationProfileScene();
50
+ this._elevationProfileView = new ElevationProfileView();
51
+ this._elevationProfileLegend = new ElevationProfileLegend();
52
+ this._elevationProfileButtonsView = new ElevationProfileButtonsView({
53
+ model: this._elevationProfileView.model
54
+ });
55
+ this._elevationProfileView.events.on("pointer", this._onElevationProfilePointer);
56
+ this._elevationProfileView.events.on("dblclick", this._onElevationProfileDblClick);
57
+ this._elevationProfileView.events.on("mouseenter", this._onElevationProfileMouseEnter);
58
+ this._elevationProfileView.events.on("mouseleave", this._onElevationProfileMouseLeave);
59
+ this._dialog = new Dialog({
60
+ title: "Elevation Profile",
61
+ visible: false,
62
+ resizable: true,
63
+ useHide: true,
64
+ top: 175,
65
+ left: 65,
66
+ width: 400,
67
+ height: 200,
68
+ minHeight: 100,
69
+ minWidth: 100
70
+ });
71
+ this._graphView = new View({
72
+ template: TEMPLATE
73
+ });
74
+ this._poiListDialog = new PointListDialog({
75
+ model: this._elevationProfileScene
76
+ });
77
+ this._toggleBtn = new ToggleButton({
78
+ classList: ["og-map-button", "og-elevationprofile_button"],
79
+ icon: ICON_BUTTON_SVG
80
+ });
81
+ this._collectProfileThrottled = throttle(() => {
82
+ let points = this._elevationProfileScene.getPointsLonLat();
83
+ this._elevationProfileView.model.collectProfile(points);
84
+ }, 250);
85
+ }
86
+ oninit() {
87
+ this._dialog.appendTo(this.planet.renderer.div);
88
+ this._graphView.appendTo(this._dialog.container);
89
+ this._toggleBtn.appendTo(this.renderer.div);
90
+ this._dialog.events.on("visibility", (v) => {
91
+ this._toggleBtn.setActive(v);
92
+ if (v) {
93
+ this.activate();
94
+ this._elevationProfileView.resize();
95
+ }
96
+ else {
97
+ this.deactivate();
98
+ }
99
+ });
100
+ this._toggleBtn.events.on("change", (isActive) => {
101
+ this._dialog.setVisibility(isActive);
102
+ });
103
+ this._elevationProfileView.appendTo(this._graphView.select(".og-elevationprofile__graph"));
104
+ this._elevationProfileView.model.bindPlanet(this.planet);
105
+ this._elevationProfileView.model.events.on("clear", () => {
106
+ this._elevationProfileScene.clear();
107
+ this._elevationProfileLegend.clear();
108
+ });
109
+ this._elevationProfileView.model.events.on("startcollecting", () => {
110
+ this._elevationProfileScene.setPointerVisibility(false);
111
+ });
112
+ this._elevationProfileView.events.on("tracklength", (length) => {
113
+ this._elevationProfileLegend.setTrackLength(length);
114
+ });
115
+ this._elevationProfileView.events.on("groundlength", (length) => {
116
+ this._elevationProfileLegend.setGroundLength(length);
117
+ });
118
+ this._elevationProfileView.events.on("warninglength", (length) => {
119
+ this._elevationProfileLegend.setWarningLength(length);
120
+ });
121
+ this._elevationProfileView.events.on("collisionlength", (length) => {
122
+ this._elevationProfileLegend.setCollisionLength(length);
123
+ });
124
+ this._poiListDialog.appendTo(this.planet.renderer.div);
125
+ this._poiListDialog.events.on("visibility", (isVisible) => {
126
+ this._elevationProfileButtonsView.pointListBtn.setActive(isVisible, true);
127
+ });
128
+ this._elevationProfileLegend.appendTo(this._graphView.select(".og-elevationprofile__menu"));
129
+ this._elevationProfileButtonsView.appendTo(this._graphView.select(".og-elevationprofile__menu"));
130
+ this._elevationProfileButtonsView.events.on("list", (isActive) => {
131
+ this._poiListDialog.setVisibility(isActive);
132
+ });
133
+ this._elevationProfileButtonsView.events.on("location", (isActive) => {
134
+ this._elevationProfileScene.flyExtent();
135
+ });
136
+ this._elevationProfileButtonsView.events.on("reset", (isActive) => {
137
+ this._elevationProfileScene.setPointerVisibility(false);
138
+ });
139
+ this._elevationProfileScene.events.on("change", this._onSceneChange);
140
+ }
141
+ onactivate() {
142
+ this.renderer.controls.mouseNavigation.deactivateDoubleClickZoom();
143
+ this.planet && this._elevationProfileScene.bindPlanet(this.planet);
144
+ this.renderer && this.renderer.addNode(this._elevationProfileScene);
145
+ }
146
+ ondeactivate() {
147
+ this._poiListDialog.setVisibility(false);
148
+ this._elevationProfileView.model.clear();
149
+ this.renderer.controls.mouseNavigation.activateDoubleClickZoom();
150
+ this.renderer && this.renderer.removeNode(this._elevationProfileScene);
151
+ this._dialog.hide();
152
+ }
153
+ }
@@ -0,0 +1,20 @@
1
+ import { IViewParams, View } from '../../ui/View';
2
+ export interface IElevationProfileLegendParams extends IViewParams {
3
+ }
4
+ export declare class ElevationProfileLegend extends View<null> {
5
+ $groundValue: HTMLElement | null;
6
+ $trackValue: HTMLElement | null;
7
+ $warningValue: HTMLElement | null;
8
+ $collisionValue: HTMLElement | null;
9
+ $trackUnits: HTMLElement | null;
10
+ $groundUnits: HTMLElement | null;
11
+ $warningUnits: HTMLElement | null;
12
+ $collisionUnits: HTMLElement | null;
13
+ constructor(params?: IElevationProfileLegendParams);
14
+ render(params: any): this;
15
+ clear(): void;
16
+ setTrackLength(trackLength: number): void;
17
+ setGroundLength(groundLength: number): void;
18
+ setWarningLength(warningLength: number): void;
19
+ setCollisionLength(collisionLength: number): void;
20
+ }