################################################################################ # # Boeing 787-8 Dreamliner Terrain Map (also used in other aircraft) # # The idea about getting a terrain map without compromising much frame-rate is # to sweep the changes across the screen instead of getting the whole screen at # once. Another idea here is to interpolate between 2 points and 'assume' what # would be there. That way, say in a line of 32, instead of getting all 32 # points, we could get just 16 and interpolate the rest to this and it would be # almost just as good. # # Licensed along with the 787-8 under GNU GPL v2 # ################################################################################ var row = 0; var RAD2DEG = 57.2957795; var DEG2RAD = 0.016774532925; var terrain = "/instrumentation/terrain-map/pixels/"; var terrain_full = "/instrumentation/terrain-map[1]/pixels/"; # Function to get Elevation at latitude and longitude var get_elevation = func (lat, lon) { var info = geodinfo(lat, lon); if (info != nil) {var elevation = info[0] * 3.2808399;} else {var elevation = -1.0; } return elevation; } var terrain_map = { init : func { me.UPDATE_INTERVAL = 0.025; me.loopid = 0; me.reset(); }, update : func { if (getprop("/instrumentation/efis/input/TERR")) { var pos_lon = getprop("/position/longitude-deg"); var pos_lat = getprop("/position/latitude-deg"); var heading = getprop("orientation/heading-magnetic-deg"); #setprop("/controls/mfd/terrain-map/range", getprop("/instrumentation/ndfull/range")); var range = getprop("/instrumentation/efis/nd/display-range"); var displaymode = getprop("instrumentation/efis[0]/nd/display-mode"); ### Same calculations but for the fullscreen ND, that means RANGE matters # First get all the points (16x16) for (var col = 1; col <= 32; col += 2) { var proj_lon = pos_lon + ((-1 * (col-16) * (range/30) * math.sin(DEG2RAD * (heading - 90))) / 60); var proj_lat = pos_lat + ((-1 * (col-16) * (range/30) * math.cos(DEG2RAD * (heading - 90))) / 60); if (displaymode == 'ARC') { #just represent ahead var point_lon = proj_lon + ((row * (range/30) / 60) * math.sin(DEG2RAD * heading)); var point_lat = proj_lat + ((row * (range/30) / 60) * math.cos(DEG2RAD * heading)); } else { # Represent ahead and back var point_lon = proj_lon + (((row-16) * (range/30) / 60) * math.sin(DEG2RAD * heading)); var point_lat = proj_lat + (((row-16) * (range/30) / 60) * math.cos(DEG2RAD * heading)); } setprop(terrain ~ "row[" ~ row ~ "]/col[" ~ col ~ "]/elevation-ft", get_elevation(point_lat, point_lon)); } # Interpolate the rest of the points in each column for (var col = 2; col <= 31; col += 2) { var elev_prev = getprop(terrain ~ "row[" ~ row ~ "]/col[" ~ (col - 1) ~ "]/elevation-ft"); var elev_next = getprop(terrain ~ "row[" ~ row ~ "]/col[" ~ (col + 1) ~ "]/elevation-ft"); var elevation = (elev_prev + elev_next) / 2; setprop(terrain ~ "row[" ~ row ~ "]/col[" ~ col ~ "]/elevation-ft", elevation); } row += 1; if (row == 32) row = 0; } }, reset : func { me.loopid += 1; me._loop_(me.loopid); }, _loop_ : func(id) { id == me.loopid or return; me.update(); settimer(func { me._loop_(id); }, me.UPDATE_INTERVAL); } }; setlistener("sim/signals/fdm-initialized", func { terrain_map.init(); print("Terrain Map ......... Initialized"); });