diff --git a/html/formatter.js b/html/formatter.js
index 0706359..1ba5584 100644
--- a/html/formatter.js
+++ b/html/formatter.js
@@ -134,7 +134,7 @@ function format_onground (alt) {
// alt in feet
function convert_altitude(alt, displayUnits) {
if (displayUnits === "metric") {
- return alt / 3.2808; // feet to meters
+ return alt * 0.3048; // feet to meters
}
return alt;
diff --git a/html/planeObject.js b/html/planeObject.js
index b472d37..ed7ce03 100644
--- a/html/planeObject.js
+++ b/html/planeObject.js
@@ -404,7 +404,7 @@ PlaneObject.prototype.updateTrack = function(now, last, serverTrack, stale) {
let newseg = { fixed: new ol.geom.LineString([projHere]),
feature: null,
estimated: false,
- ground: on_ground,
+ ground: (this.altitude == "ground"),
altitude: this.alt_rounded,
alt_real: this.altitude,
alt_geom: this.alt_geom,
@@ -592,12 +592,12 @@ PlaneObject.prototype.updateTrack = function(now, last, serverTrack, stale) {
this.track_linesegs.push({ fixed: new ol.geom.LineString(points),
feature: null,
estimated: estimated,
+ ground: (this.prev_alt == "ground"),
altitude: this.prev_alt_rounded,
alt_real: this.prev_alt,
alt_geom: this.prev_alt_geom,
position: this.prev_position,
speed: this.prev_speed,
- ground: on_ground,
ts: this.prev_time,
track: this.prev_rot,
leg: is_leg,
@@ -1191,12 +1191,12 @@ PlaneObject.prototype.processTrace = function() {
this.track_linesegs.push({ fixed: new ol.geom.LineString([proj]),
feature: null,
estimated: false,
+ ground: (this.altitude == "ground"),
altitude: this.alt_rounded,
alt_real: this.altitude,
alt_geom: this.alt_geom,
position: this.position,
speed: this.speed,
- ground: (this.altitude == "ground"),
ts: this.position_time,
track: this.rotation,
rId: this.rId,
@@ -2512,12 +2512,12 @@ PlaneObject.prototype.cross180 = function(on_ground, is_leg) {
this.track_linesegs.push({ fixed: new ol.geom.LineString([seg1.shift()]),
feature: null,
estimated: true,
+ ground: (this.prev_alt == "ground"),
altitude: this.prev_alt_rounded,
alt_real: this.prev_alt,
alt_geom: this.prev_alt_geom,
position: this.prev_position,
speed: this.prev_speed,
- ground: on_ground,
ts: this.prev_time,
track: this.prev_rot,
leg: is_leg,
@@ -2527,12 +2527,12 @@ PlaneObject.prototype.cross180 = function(on_ground, is_leg) {
this.track_linesegs.push({ fixed: new ol.geom.LineString(seg1),
feature: null,
estimated: true,
+ ground: (this.prev_alt == "ground"),
altitude: this.prev_alt_rounded,
alt_real: this.prev_alt,
alt_geom: this.prev_alt_geom,
position: this.prev_position,
speed: this.prev_speed,
- ground: on_ground,
track: this.prev_rot,
ts: NaN,
noLabel: true,
@@ -2542,12 +2542,12 @@ PlaneObject.prototype.cross180 = function(on_ground, is_leg) {
this.track_linesegs.push({ fixed: new ol.geom.LineString(seg2),
feature: null,
estimated: true,
+ ground: (this.prev_alt == "ground"),
altitude: this.prev_alt_rounded,
alt_real: this.prev_alt,
alt_geom: this.prev_alt_geom,
position: this.prev_position,
speed: this.prev_speed,
- ground: on_ground,
track: this.prev_rot,
ts: NaN,
noLabel: true,
diff --git a/html/script.js b/html/script.js
index 35113bb..813af5e 100644
--- a/html/script.js
+++ b/html/script.js
@@ -7270,14 +7270,16 @@ function baseExportFilenameForAircrafts(aircrafts) {
// Returns an array of {pos, alt, ts} for an aircraft.
function coordsForExport(plane) {
- var coords = [];
- var numSegs = plane.track_linesegs.length;
+ let coords = [];
+ let numSegs = plane.track_linesegs.length;
for (let i = 0; i < numSegs; i++) {
- const proj = plane.track_linesegs[i].fixed.getCoordinates()[0];
- if (proj) {
- const pos = ol.proj.toLonLat(proj);
- let alt = plane.track_linesegs[i].alt_geom;
- if (alt == null) {
+ const pos = plane.track_linesegs[i].position;
+ if (pos) {
+ let alt = null;
+ if (plane.track_linesegs[i].alt_geom != null) {
+ alt = plane.track_linesegs[i].alt_geom;
+ alt = Math.round(alt * 0.3048); // convert ft to m
+ } else if (plane.track_linesegs[i].alt_real != null) {
alt = plane.track_linesegs[i].alt_real;
// Attempt to correct altitude. This could be better?
//
@@ -7285,21 +7287,21 @@ function coordsForExport(plane) {
// 25 feet is the quantum of transponder reporting. 0 altitude
// could be reported as -25, so just add 25.
alt = (alt + 950 + 25) * 0.3048;
- } else {
- alt = alt * 0.3048;
}
if (plane.track_linesegs[i].ground) {
- alt = NaN;
+ alt = "ground";
} else if (alt != null && egmLoaded) {
- alt = egm96.ellipsoidToEgm96(pos[1], pos[0], alt);
+ // alt is in meters at this point
+ alt = Math.round(egm96.ellipsoidToEgm96(pos[1], pos[0], alt));
}
const ts = new Date(plane.track_linesegs[i].ts * 1000.0);
- if (!alt) {
+ if (alt == null) {
console.log(`Skipping, no altitude: ${i} ${pos} ${ts}`);
continue;
}
- coords.push({ pos, alt: alt, ts });
+ //console.log(`exporting coord: ${i} ${pos} ${alt} ${ts}`);
+ coords.push({ pos: pos, alt: alt, ts: ts});
} else {
console.log(`Skipping ${i}`);
}
@@ -7366,7 +7368,7 @@ function loadEGM() {
}
function adjust_geom_alt(alt, pos) {
if (geomUseEGM && egmLoaded) {
- return egm96.ellipsoidToEgm96(pos[1], pos[0], alt);
+ return egm96.ellipsoidToEgm96(pos[1], pos[0], alt * 0.3048) / 0.3048;
} else {
return alt;
}
@@ -7384,39 +7386,75 @@ function exportKML() {
const planes = selectedPlanes();
const folders = [];
- for (let i = 0; i < planes.length; i++) {
- const plane = planes[i];
- const coords = coordsForExport(plane);
- const whenObjs = coords.map((c) => {
- const date = `${c.ts.getUTCFullYear()}-${zeroPad(c.ts.getUTCMonth() + 1, 2)}-${zeroPad(c.ts.getUTCDate(), 2)}`;
- const time = `T${zeroPad(c.ts.getUTCHours(), 2)}:${zeroPad(c.ts.getUTCMinutes(), 2)}:${zeroPad(c.ts.getUTCSeconds(), 2)}.${zeroPad(c.ts.getUTCMilliseconds(), 3)}Z`;
- return ["when", {}, date + time];
- });
- const coordObjs = coords.map((c) => ["gx:coord", {}, `${c.pos[0]} ${c.pos[1]} ${c.alt}`]);
- var folder = ["Folder", {},
- ["name", {}, `${(plane.registration || plane.icao).toUpperCase()} track`],
- ["Placemark", {},
- ["name", {}, (plane.registration || plane.icao).toUpperCase()],
- ["Style", {},
- ["LineStyle", {},
- ["color", {}, RGBColorToKMLColor(EXPORT_RGB_COLORS[i % EXPORT_RGB_COLORS.length])],
- ["width", {}, 4]
- ],
- ["IconStyle", {},
- ["Icon", {},
- ["href", {}, "http://maps.google.com/mapfiles/kml/shapes/airports.png"]
- ]
- ]
- ],
- ["gx:Track", {},
- ["altitudeMode", {}, "absolute"],
- ["extrude", {}, "1"],
- ["tessellate", {}, "1"],
- ...whenObjs,
- ...coordObjs
- ]
- ]
+ for (let planeIndex = 0; planeIndex < planes.length; planeIndex++) {
+ const plane = planes[planeIndex];
+ let folder = ["Folder", {},
+ ["name", {}, `${(plane.registration || plane.icao).toUpperCase()} track`]
];
+ const coords = coordsForExport(plane);
+ let sections = [];
+ let currentSection = null;
+ let lastGround = null;
+ let lastC = null;
+ for (let i in coords) {
+ const c = coords[i];
+ const ground = (c.alt == "ground");
+ if (ground !== lastGround) {
+ // when changing between airborne and ground, create new section
+ if (lastC && currentSection) {
+ // double up last coordinate to work around strange google earth transparency
+ currentSection.coords.push(lastC);
+ }
+ currentSection = { ground: ground, coords: [] };
+ sections.push(currentSection);
+ }
+ lastGround = ground;
+ if (ground) {
+ c.alt = 0; // set KML altitude to zero
+ }
+ currentSection.coords.push(c);
+ lastC = c;
+ }
+ if (lastC && currentSection) {
+ // double up last coordinate to work around strange google earth transparency
+ currentSection.coords.push(lastC);
+ }
+ for (let i in sections) {
+ console.log("section " + i);
+ const s = sections[i];
+ const coords = s.coords;
+ const ground = s.ground;
+ const whenObjs = coords.map((c) => {
+ const date = `${c.ts.getUTCFullYear()}-${zeroPad(c.ts.getUTCMonth() + 1, 2)}-${zeroPad(c.ts.getUTCDate(), 2)}`;
+ const time = `T${zeroPad(c.ts.getUTCHours(), 2)}:${zeroPad(c.ts.getUTCMinutes(), 2)}:${zeroPad(c.ts.getUTCSeconds(), 2)}.${zeroPad(c.ts.getUTCMilliseconds(), 3)}Z`;
+ return ["when", {}, date + time];
+ });
+ const coordObjs = coords.map((c) => {
+ return ["gx:coord", {}, `${c.pos[0]} ${c.pos[1]} ${c.alt}`];
+ });
+ folder.push(
+ ["Placemark", {},
+ ["name", {}, (plane.registration || plane.icao).toUpperCase()],
+ ["Style", {},
+ ["LineStyle", {},
+ ["color", {}, RGBColorToKMLColor(EXPORT_RGB_COLORS[planeIndex % EXPORT_RGB_COLORS.length])],
+ ["width", {}, 4]
+ ],
+ ["IconStyle", {},
+ ["Icon", {},
+ ["href", {}, "http://maps.google.com/mapfiles/kml/shapes/airports.png"]
+ ]
+ ]
+ ],
+ ["gx:Track", {},
+ ["altitudeMode", {}, ground ? "clampToGround" : "absolute"],
+ ["extrude", {}, ground ? "0" : "1"],
+ ...whenObjs,
+ ...coordObjs
+ ]
+ ]
+ );
+ }
folders.push(folder);
}
const filename = baseExportFilenameForAircrafts(planes);