generate separate ground / air segments for KML

fix some trace internals
This commit is contained in:
Matthias Wirth
2022-01-10 10:35:42 +01:00
parent 35b57be548
commit d9596a2670
3 changed files with 91 additions and 53 deletions

View File

@@ -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;

View File

@@ -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,

View File

@@ -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);