diff --git a/CHANGELOG.md b/CHANGELOG.md index d8c9d5a..66bb72f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- Added `flyOver` property to waypoints +- Added `finish` property to missions - Added new cloud layers - Improved handling of Garmin `fpl` files - Prioritizing waypoints in GeoJson diff --git a/dist/Aerofly/Mission.js b/dist/Aerofly/Mission.js index b1d4f10..55702d8 100644 --- a/dist/Aerofly/Mission.js +++ b/dist/Aerofly/Mission.js @@ -39,6 +39,7 @@ export class Mission { * True heading of aircraft in Degrees on exit */ this.destination_dir = 0; + this.finish = null; this.conditions = new MissionConditions(); this.checkpoints = []; /** @@ -303,6 +304,7 @@ export class Mission { break; } this.conditions.fromMainMcf(mainMcf); + this.finish = null; let lastPosition = null; this.checkpoints = mainMcf.navigation.Route.Ways.filter((w) => { // Please not that procedure waypoints cannot be restored as of now @@ -373,6 +375,7 @@ export class Mission { } // Assuming non AFS4 flight plans to start on the ground ;) this.flight_setting = Mission.FLIGHT_SETTING_TAXI; + this.finish = null; this.checkpoints = gpl.waypoints.map((w, i) => { var _a; let cp = new MissionCheckpoint(); @@ -787,6 +790,8 @@ export class Mission { this.calculateCheckpoints(); } toString() { + var _a, _b; + const finish = (_b = (_a = this.finish) === null || _a === void 0 ? void 0 : _a.toStringTargetPlane('finish')) !== null && _b !== void 0 ? _b : ''; let string = ` // Exported by Aerofly Missionsgerät <[tmmission_definition][mission][] <[string8][title][${Quote.tmc(this.title)}]> @@ -804,7 +809,7 @@ export class Mission { <[float64] [destination_dir] [${this.destination_dir}]> //<[float64] [cruise_altitude] [${this.cruise_altitude}]> //<[float64] [cruise_speed] [${this.cruise_speed}]> -${this.conditions} <[list_tmmission_checkpoint][checkpoints][] +${this.conditions + finish} <[list_tmmission_checkpoint][checkpoints][] `; this.checkpoints.forEach((c, i) => { string += c.toString(i); @@ -816,7 +821,7 @@ ${this.conditions} <[list_tmmission_checkpoint][checkpoints][] return string; } hydrate(json) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x; + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y; this._title = (_a = json._title) !== null && _a !== void 0 ? _a : this._title; this._description = (_b = json._description) !== null && _b !== void 0 ? _b : this._description; this.flight_setting = (_c = json.flight_setting) !== null && _c !== void 0 ? _c : this.flight_setting; @@ -842,6 +847,7 @@ ${this.conditions} <[list_tmmission_checkpoint][checkpoints][] this.cruise_altitude = (_w = json.cruise_altitude) !== null && _w !== void 0 ? _w : this.cruise_altitude; this.turn_time = (_x = json.turn_time) !== null && _x !== void 0 ? _x : this.turn_time; this.conditions.hydrate(json.conditions); + this.finish = (_y = json.finish) !== null && _y !== void 0 ? _y : this.finish; this.checkpoints = json.checkpoints.map((c) => { const cx = new MissionCheckpoint(); cx.hydrate(c); @@ -892,6 +898,7 @@ export class MissionFactory extends FileParser { mission.conditions.visibility = this.getNumber(tmmission_conditions, "visibility"); mission.conditions.cloud.cover = this.getNumber(tmmission_conditions, "cloud_cover"); mission.conditions.cloud.height = this.getNumber(tmmission_conditions, "cloud_base"); + mission.finish = null; mission.checkpoints = list_tmmission_checkpoint .split("<[tmmission_checkpoint") .slice(1) diff --git a/dist/Aerofly/MissionCheckpoint.js b/dist/Aerofly/MissionCheckpoint.js index 6e17ab0..ae7fb4e 100644 --- a/dist/Aerofly/MissionCheckpoint.js +++ b/dist/Aerofly/MissionCheckpoint.js @@ -31,6 +31,10 @@ export class MissionCheckpoint { * @see MissionCheckpoint.rawFreqency */ this.frequency = 0; + /** + * If waypoint is meant to be flown over. Else turn anticipation will be used. + */ + this.flyOver = false; /** * Not official: In kts TAS */ @@ -189,6 +193,11 @@ export class MissionCheckpoint { this.slope = altDifference / this.distance_m; } toString(index) { + let flyOver = ""; + if (this.type === MissionCheckpoint.TYPE_WAYPOINT) { + flyOver = ` <[bool][FlyOver][${this.flyOver ? "true" : "false"}]> + `; + } return ` <[tmmission_checkpoint][element][${index}] <[string8u][type][${Quote.tmc(this.type)}]> <[string8u][name][${Quote.tmc(this.name)}]> @@ -199,7 +208,14 @@ export class MissionCheckpoint { <[float64][slope][${this.slope}]> // ${this.slope_deg.toFixed(1)} deg <[float64][length][${this.length}]> <[float64][frequency][${this.frequency.toFixed()}]> - > +${flyOver} > +`; + } + toStringTargetPlane(name = "finish") { + return ` <[tmmission_target_plane][${name}][] + <[vector2_float64][lon_lat][${this.lon_lat.lon} ${this.lon_lat.lat}]> + <[float64][direction][${this.direction}]> + > `; } hydrate(cp) { diff --git a/dist/Export/GeoJson.js b/dist/Export/GeoJson.js index ea1ae68..7ea2738 100644 --- a/dist/Export/GeoJson.js +++ b/dist/Export/GeoJson.js @@ -71,7 +71,7 @@ export class GeoJson { altitude: c.lon_lat.altitude_m, direction: c.direction, frequency: c.frequency_string, - "marker-symbol": this.getGeoJsonIcon(c), + "marker-symbol": this.getGeoJsonIcon(c, mission.finish), "marker-color": c.type === MissionCheckpoint.TYPE_ORIGIN || c.type === MissionCheckpoint.TYPE_DESTINATION ? "#5e6eba" : "#555555", @@ -199,7 +199,8 @@ export class GeoJson { turnDegrees += 360; } const turnAnticipationDistance = Math.tan(((Math.abs(turnDegrees) / 180) * Math.PI) / 2) * turnRadius; - if (Math.abs(turnDegrees) < 150 && + if (!c.flyOver && + Math.abs(turnDegrees) < 150 && turnAnticipationDistance <= Math.min(c.distance / 2, nextCheckpoint.distance / 2)) { // Fly-by const segments = Math.ceil(Math.abs(turnDegrees) / (360 / segmentsPerCircle)); @@ -215,6 +216,7 @@ export class GeoJson { //lineCoordinates.push(this.getGeoJsonPosition(entry)); } else { + console.log("Fly-over"); // Fly-over // @see https://en.wikipedia.org/wiki/Circular_segment turnDegrees *= 2; @@ -259,7 +261,10 @@ export class GeoJson { getGeoJsonPosition(entry) { return entry.altitude_m ? [entry.lon, entry.lat, entry.altitude_m] : [entry.lon, entry.lat]; } - getGeoJsonIcon(cp) { + getGeoJsonIcon(cp, finishCp) { + if (finishCp && finishCp === cp) { + return "af-large_airbase"; + } switch (cp.type_extended) { case MissionCheckpoint.TYPE_DESTINATION: return "af-large_airport"; diff --git a/dist/Web/App.js b/dist/Web/App.js index aff9d81..5a67b8b 100644 --- a/dist/Web/App.js +++ b/dist/Web/App.js @@ -126,6 +126,7 @@ export class App { this.showFlightplan(App.SHOW_CHECKPOINTS); } handleEventClickWaypointEdit(target) { + var _a; const type = target.getAttribute("data-type"); const waypointId = Number(target.closest("dialog").getAttribute("data-cp-id")); switch (type) { @@ -138,6 +139,14 @@ export class App { case "add-after": this.mission.addCheckpointAfter(waypointId, 3, 1000); break; + case "make-finish": + const currentWaypoint = this.mission.checkpoints[waypointId]; + this.mission.finish = + currentWaypoint === this.mission.finish ? null : (_a = this.mission.checkpoints[waypointId]) !== null && _a !== void 0 ? _a : null; + break; + case "toggle-flyover": + this.mission.checkpoints[waypointId].flyOver = !this.mission.checkpoints[waypointId].flyOver; + break; } this.handleEventClickModalClose(target); this.mission.calculateCheckpoints(); diff --git a/dist/index.html b/dist/index.html index e94ebc0..d4c1484 100644 --- a/dist/index.html +++ b/dist/index.html @@ -387,6 +387,8 @@