1 # Draw 3 degree glide slope tunnel for the nearest airport's most suitable runway
2 # considering wind direction and runway size.
3 # Activate with --prop:sim/rendering/glide-slope-tunnel=1 or via Help menu
5 var MARKER = "Models/Geometry/square.xml"; # tunnel marker
6 var DIST = 1000; # distance between markers
7 var NUM = 30; # number of tunnel markers
8 var ANGLE = 3 * math.pi / 180; # glide slope angle in radian
9 var HOFFSET = 274; # distance between begin of runway and touchdown area (900 ft)
10 var INTERVAL = 5; # check for nearest airport
12 var voffset = DIST * math.sin(ANGLE) / math.cos(ANGLE);
18 var normdeg = func(a) {
27 # Find best runway for current wind direction (or 270), also considering length and width.
29 var best_runway = func(apt) {
30 var wind_speed = getprop("/environment/wind-speed-kt");
31 var wind_from = wind_speed ? getprop("/environment/wind-from-heading-deg") : 270;
35 foreach (var r; keys(apt.runways)) {
36 var curr = apt.runways[r];
37 var deviation = math.abs(normdeg(wind_from - curr.heading)) + 1e-20;
38 var v = (0.01 * curr.length + 0.01 * curr.width) / deviation;
49 # Draw 3 degree glide slope tunnel.
51 var draw_tunnel = func(rwy) {
52 var m = geo.Coord.new().set_latlon(rwy.lat, rwy.lon);
53 m.apply_course_distance(rwy.heading + 180, rwy.length / 2 - rwy.threshold - HOFFSET);
55 var g = geodinfo(m.lat(), m.lon());
56 var elev = g != nil ? g[0] : apt.elevation;
57 forindex (var i; tunnel) {
62 tunnel[i] = geo.put_model(MARKER, m, rwy.heading);
63 m.apply_course_distance(rwy.heading + 180, DIST);
70 id == loopid or return;
71 var a = airportinfo();
72 if (apt == nil or apt.id != a.id) {
75 foreach (var rwy; keys(apt.runways))
80 draw_tunnel(best_runway(apt));
81 gui.popupTip(apt.id ~ " - \"" ~ apt.name ~ "\"", 6);
84 settimer(func loop(id), INTERVAL);
90 var fdm_init_listener = _setlistener("/sim/signals/fdm-initialized", func {
91 removelistener(fdm_init_listener); # uninstall, so we're only called once
92 # remove top bar unless otherwise specified
93 var top = props.globals.initNode("/sim/model/geometry/square/top", 1, "BOOL");
95 setlistener("/sim/rendering/glide-slope-tunnel", func(n) {
102 forindex (var i; tunnel) {
103 if (tunnel[i] != nil) {