@openglobus/og 0.13.5 → 0.13.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.
@@ -42,17 +42,179 @@ export class KML extends Vector {
42
42
  _extractCoordonatesFromKml(xmlDoc) {
43
43
  const raw = Array.from(xmlDoc.getElementsByTagName("coordinates"));
44
44
  const rawText = raw.map(item => item.textContent.trim());
45
- const coordinates = rawText.map(item =>
45
+ const coordinates = rawText.map(item =>
46
46
  item
47
- .replace(/\n/g, " ")
48
- .replace(/\t/g, " ")
49
- .replace(/ +/g," ")
50
- .split(" ")
51
- .map((co) => co.split(",").map(parseFloat))
47
+ .replace(/\n/g, " ")
48
+ .replace(/\t/g, " ")
49
+ .replace(/ +/g, " ")
50
+ .split(" ")
51
+ .map((co) => co.split(",").map(parseFloat))
52
52
  );
53
53
  return coordinates;
54
54
  }
55
55
 
56
+ /**
57
+ * @private
58
+ */
59
+ _AGBRtoRGBA(agbr) {
60
+ if (!agbr || agbr.length != 8) return
61
+
62
+ const a = parseInt(agbr.slice(0, 2), 16) / 255;
63
+ const b = parseInt(agbr.slice(2, 4), 16);
64
+ const g = parseInt(agbr.slice(4, 6), 16);
65
+ const r = parseInt(agbr.slice(6, 8), 16);
66
+
67
+ return `rgba(${r},${g},${b},${a})`;
68
+ }
69
+
70
+ /**
71
+ * @private
72
+ returns array of longitude, latitude, altitude (altitude optional)
73
+ */
74
+ _parseKMLcoordinates(coords) {
75
+ const coordinates = coords.innerHTML.trim()
76
+ .replace(/\n/g, ' ')
77
+ .replace(/\t/g, ' ')
78
+ .replace(/ +/g, ' ')
79
+ .split(" ")
80
+ .map((co) => co.split(",").map(parseFloat))
81
+
82
+ return coordinates;
83
+ }
84
+
85
+ /**
86
+ * @private
87
+ */
88
+ _kmlPlacemarkToEntity(placemark, extent) {
89
+ if (!placemark) return;
90
+
91
+ const nameTags = Array.from(placemark.getElementsByTagName("name"))
92
+ const name = nameTags && nameTags[0]?.innerHTML?.trim() || '';
93
+
94
+ const { iconHeading, iconURL, iconColor, lineWidth, lineColor } = this._extractStyle(placemark);
95
+
96
+ // TODO handle MultiGeometry
97
+
98
+ const lonLats = [];
99
+ for (const coord of placemark.getElementsByTagName("coordinates")) {
100
+ const coordinates = this._parseKMLcoordinates(coord) || [[0, 0, 0]]
101
+
102
+ for (const lonlatalt of coordinates) {
103
+ const [lon, lat, alt] = lonlatalt
104
+
105
+ lonLats.push(new LonLat(lon, lat, alt));
106
+
107
+ if (lon < extent.southWest.lon) extent.southWest.lon = lon;
108
+ if (lat < extent.southWest.lat) extent.southWest.lat = lat;
109
+ if (lon > extent.northEast.lon) extent.northEast.lon = lon;
110
+ if (lat > extent.northEast.lat) extent.northEast.lat = lat;
111
+ }
112
+ }
113
+
114
+ if (lonLats.length === 1) {
115
+ const hdgrad = iconHeading * 0.01745329; // radians
116
+
117
+ return new Entity({
118
+ name,
119
+ lonlat: lonLats[0],
120
+ billboard: {
121
+ src: iconURL,
122
+ size: [24, 24],
123
+ color: iconColor,
124
+ rotation: hdgrad
125
+ },
126
+ properties: {
127
+ color: iconColor,
128
+ heading: iconHeading
129
+ }
130
+ });
131
+
132
+ } else {
133
+ return new Entity({
134
+ polyline: {
135
+ pathLonLat: [lonLats],
136
+ thickness: lineWidth,
137
+ color: lineColor,
138
+ isClosed: false
139
+ }
140
+ });
141
+ }
142
+ }
143
+
144
+ _extractStyle(placemark) {
145
+ let iconColor;
146
+ let iconHeading;
147
+ let iconURL;
148
+ let lineColor;
149
+ let lineWidth;
150
+
151
+ const style = placemark.getElementsByTagName("Style")[0];
152
+ if (style) {
153
+ let iconstyle = style.getElementsByTagName("IconStyle")[0];
154
+ if (iconstyle) {
155
+ let color = iconstyle.getElementsByTagName("color")[0];
156
+ if (color)
157
+ iconColor = this._AGBRtoRGBA(color.innerHTML.trim());
158
+
159
+ let heading = iconstyle.getElementsByTagName("heading")[0];
160
+ if (heading) {
161
+ const hdg = parseFloat(heading.innerHTML.trim());
162
+ if (hdg >= 0 && hdg <= 360)
163
+ iconHeading = hdg % 360;
164
+ }
165
+
166
+ let icon = iconstyle.getElementsByTagName("Icon")[0];
167
+ if (icon) {
168
+ let href = icon.getElementsByTagName("href")[0];
169
+ if (href) {
170
+ iconURL = href.innerHTML.trim();
171
+ }
172
+ }
173
+ }
174
+
175
+ let linestyle = style.getElementsByTagName("LineStyle")[0];
176
+ if (linestyle) {
177
+ let color = linestyle.getElementsByTagName("color")[0];
178
+ if (color)
179
+ lineColor = this._AGBRtoRGBA(color.innerHTML.trim());
180
+ let width = linestyle.getElementsByTagName("width")[0];
181
+ if (width !== undefined)
182
+ lineWidth = parseFloat(width.innerHTML.trim());
183
+ }
184
+ }
185
+
186
+ if (!iconColor) iconColor = "#FFFFFF"
187
+ if (!iconHeading) iconHeading = 0
188
+ if (!iconURL) iconURL = "https://openglobus.org/examples/billboards/carrot.png"
189
+
190
+ if (!lineColor) lineColor = "#FFFFFF"
191
+ if (!lineWidth) lineWidth = 1
192
+
193
+ return { iconHeading, iconURL, iconColor, lineWidth, lineColor };
194
+ }
195
+
196
+ _parseKML(xml, extent, entities = undefined) {
197
+ if (!entities)
198
+ entities = [];
199
+
200
+ if (xml.documentElement.nodeName !== "kml")
201
+ return entities;
202
+
203
+ for (const placemark of xml.getElementsByTagName("Placemark")) {
204
+ const entity = this._kmlPlacemarkToEntity(placemark, extent);
205
+ if (entity) entities.push(entity);
206
+ }
207
+
208
+ return entities;
209
+ }
210
+
211
+ _convertKMLintoEntities(xml) {
212
+ const extent = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
213
+ const entities = this._parseKML(xml, extent);
214
+
215
+ return { entities, extent }
216
+ }
217
+
56
218
  /**
57
219
  * Creates billboards or polylines from array of lonlat.
58
220
  * @public
@@ -129,6 +291,7 @@ export class KML extends Vector {
129
291
  * @returns {Promise<{entities: Entity[], extent: Extent}>}
130
292
  */
131
293
  async addKmlFromFiles(kmls, color = null, billboard = null) {
294
+ if (!Array.isArray(kmls)) return null
132
295
  const kmlObjs = await Promise.all(kmls.map(this._getXmlContent));
133
296
  const coordonates = kmlObjs.map(this._extractCoordonatesFromKml);
134
297
  const { entities, extent } = this._convertCoordonatesIntoEntities(
@@ -179,14 +342,20 @@ export class KML extends Vector {
179
342
  */
180
343
  async addKmlFromUrl(url, color = null, billboard = null) {
181
344
  const kml = await this._getKmlFromUrl(url);
182
- const coordonates = this._extractCoordonatesFromKml(kml);
183
- const { entities, extent } = this._convertCoordonatesIntoEntities(
184
- [coordonates],
185
- color || this._color,
186
- billboard || this._billboard
187
- );
345
+ /*
346
+ const coordonates = this._extractCoordonatesFromKml(kml);
347
+ const { entities, extent } = this._convertCoordonatesIntoEntities(
348
+ [coordonates],
349
+ color || this._color,
350
+ billboard || this._billboard
351
+ );
352
+ */
353
+ const { entities, extent } = this._convertKMLintoEntities(kml);
354
+
188
355
  this._extent = this._expandExtents(this._extent, extent);
356
+
189
357
  entities.forEach(this.add.bind(this));
358
+
190
359
  return { entities, extent };
191
360
  }
192
361
  }
@@ -413,8 +413,10 @@ class Layer {
413
413
  * @param {string} html - HTML code that represents layer attribution, it could be just a text.
414
414
  */
415
415
  setAttribution(html) {
416
- this._attribution = html;
417
- this._planet && this._planet.updateAttributionsList();
416
+ if (this._attribution !== html) {
417
+ this._attribution = html;
418
+ this._planet && this._planet.updateAttributionsList();
419
+ }
418
420
  }
419
421
 
420
422
  /**
@@ -161,6 +161,8 @@ class RendererEvents extends Events {
161
161
  prev_x: 0,
162
162
  /** Previous touch Y coordinate. */
163
163
  prev_y: 0,
164
+ /** Screen touch position world direction. */
165
+ direction: new Vec3(),
164
166
  /** JavaScript touching system event message. */
165
167
  sys: null,
166
168
  /** Current touched(picking) object. */
@@ -222,6 +224,13 @@ class RendererEvents extends Events {
222
224
  this.mouseState.x,
223
225
  this.mouseState.y
224
226
  );
227
+ //
228
+ // TODO: Replace in some other place with a thought that we do
229
+ // not need to make unproject when we do not make touching
230
+ this.touchState.direction = this.renderer.activeCamera.unproject(
231
+ this.touchState.x,
232
+ this.touchState.y
233
+ );
225
234
  this.entityPickingEvents();
226
235
  this._keyboardHandler.handleEvents();
227
236
  this.handleMouseEvents();
@@ -493,7 +502,7 @@ class RendererEvents extends Events {
493
502
  var ts = this.touchState;
494
503
  ts.sys = event;
495
504
 
496
- ts.clienX = event.touches.item(0).clientX - event.offsetLeft;
505
+ ts.clientX = event.touches.item(0).clientX - event.offsetLeft;
497
506
  ts.clientY = event.touches.item(0).clientY - event.offsetTop;
498
507
 
499
508
  let h = this.renderer.handler;
@@ -569,8 +578,13 @@ class RendererEvents extends Events {
569
578
 
570
579
  ts.sys = event;
571
580
  ts.moving = true;
572
- // this._dblTchBegins = 0;
573
- // this._oneTouchStart = false;
581
+
582
+ var dX = ts.x - ts.prev_x
583
+ var dY = ts.y - ts.prev_y
584
+ if (Math.abs(dX) > 9 || Math.abs(dY) > 9) {
585
+ this._dblTchBegins = 0;
586
+ this._oneTouchStart = false;
587
+ }
574
588
  }
575
589
 
576
590
  /**
@@ -613,21 +613,36 @@ export class Planet extends RenderNode {
613
613
  this._quadTree.destroyBranches();
614
614
  }
615
615
 
616
- if (terrain._geoid) {
617
- if (!terrain._geoid.model) {
618
- terrain._geoid.model = null;
619
- Geoid.loadModel(terrain._geoid.src)
620
- .then((m) => {
621
- terrain.getGeoid().setModel(m);
622
- this._plainSegmentWorker.setGeoid(terrain.getGeoid());
623
- })
624
- .catch((err) => {
625
- console.log(err);
626
- });
627
- } else {
628
- this._plainSegmentWorker.setGeoid(terrain.getGeoid());
629
- }
616
+ //if (terrain._geoid) {
617
+
618
+ if (terrain._geoid.model) {
619
+ this._plainSegmentWorker.setGeoid(terrain.getGeoid());
620
+ terrain._isReady = true;
621
+ } else {
622
+ Geoid.loadModel(terrain._geoid.src)
623
+ .then((m) => {
624
+ terrain.getGeoid().setModel(m);
625
+ this._plainSegmentWorker.setGeoid(terrain.getGeoid());
626
+ terrain._isReady = true;
627
+ })
628
+ .catch((err) => {
629
+ console.log(err);
630
+ });
630
631
  }
632
+
633
+ // if (!terrain._geoid.model) {
634
+ // Geoid.loadModel(terrain._geoid.src)
635
+ // .then((m) => {
636
+ // terrain.getGeoid().setModel(m);
637
+ // this._plainSegmentWorker.setGeoid(terrain.getGeoid());
638
+ // })
639
+ // .catch((err) => {
640
+ // console.log(err);
641
+ // });
642
+ // } else {
643
+ // this._plainSegmentWorker.setGeoid(terrain.getGeoid());
644
+ // }
645
+ //}
631
646
  }
632
647
 
633
648
  /**
@@ -917,15 +932,7 @@ export class Planet extends RenderNode {
917
932
  }
918
933
  }
919
934
 
920
- if (this.renderer) {
921
- if (html.length) {
922
- this.renderer.div.attributions.style.display = "block";
923
- this.renderer.div.attributions.innerHTML = "<ul>" + html + "</ul>";
924
- } else {
925
- this.renderer.div.attributions.style.display = "none";
926
- this.renderer.div.attributions.innerHTML = "";
927
- }
928
- }
935
+ this._applyAttribution(html)
929
936
  }
930
937
 
931
938
  /**
@@ -971,17 +978,28 @@ export class Planet extends RenderNode {
971
978
  }
972
979
  }
973
980
 
981
+ this._applyAttribution(html);
982
+
983
+ this._sortLayers();
984
+ }
985
+
986
+ /**
987
+ * Apply to render list of layer attributions
988
+ * @private
989
+ */
990
+ _applyAttribution(html) {
974
991
  if (this.renderer) {
975
992
  if (html.length) {
976
- this.renderer.div.attributions.style.display = "block";
977
- this.renderer.div.attributions.innerHTML = "<ul>" + html + "</ul>";
993
+ html = "<ul>" + html + "</ul>";
994
+ if (this.renderer.div.attributions.innerHTML !== html) {
995
+ this.renderer.div.attributions.style.display = "block";
996
+ this.renderer.div.attributions.innerHTML = html;
997
+ }
978
998
  } else {
979
999
  this.renderer.div.attributions.style.display = "none";
980
1000
  this.renderer.div.attributions.innerHTML = "";
981
1001
  }
982
1002
  }
983
-
984
- this._sortLayers();
985
1003
  }
986
1004
 
987
1005
  /**