X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FEnvironment%2Fenvironment.cxx;h=5707eea96add221341050117603cfa10edd00b4c;hb=cee943076ca56cfe4686df8629b55714d362aff0;hp=bd0f8039b680589e14c99970022d924d466addbf;hpb=62a359cc4a338b2f8b720edf8183ab5b69710b14;p=flightgear.git diff --git a/src/Environment/environment.cxx b/src/Environment/environment.cxx index bd0f8039b..5707eea96 100644 --- a/src/Environment/environment.cxx +++ b/src/Environment/environment.cxx @@ -16,74 +16,76 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // -// $Id$ - #ifdef HAVE_CONFIG_H # include #endif -#ifdef HAVE_WINDOWS_H -# include -#endif - #include -#include +#include -#include -#include -#include -#include +#include +#include #include
-#include "environment.hxx" +#include "environment.hxx" +#include "atmosphere.hxx" //////////////////////////////////////////////////////////////////////// // Atmosphere model. //////////////////////////////////////////////////////////////////////// -// Copied from YASim Atmosphere.cxx, with m converted to ft, degK -// converted to degC, Pa converted to inHG, and kg/m^3 converted to -// slug/ft^3; they were then converted to deltas from the sea-level -// defaults (approx. 15degC, 29.92inHG, and 0.00237slugs/ft^3). +#ifdef USING_TABLES -// Original comment from YASim: +// Calculated based on the ISA standard day, as found at e.g. +// http://www.av8n.com/physics/altimetry.htm -// Copied from McCormick, who got it from "The ARDC Model Atmosphere" -// Note that there's an error in the text in the first entry, -// McCormick lists 299.16/101325/1.22500, but those don't agree with -// R=287. I chose to correct the temperature to 288.20, since 79F is -// pretty hot for a "standard" atmosphere. - -// Elevation (ft), temperature factor (degK), pressure factor (inHG) +// Each line of data has 3 elements: +// Elevation (ft), +// temperature factor (dimensionless ratio of absolute temp), +// pressure factor (dimensionless ratio) static double atmosphere_data[][3] = { - { 0.00, 1.00, 1.000 }, - { 2952.76, 0.98, 0.898 }, - { 5905.51, 0.96, 0.804 }, - { 8858.27, 0.94, 0.719 }, - { 11811.02, 0.92, 0.641 }, - { 14763.78, 0.90, 0.570 }, - { 17716.54, 0.88, 0.506 }, - { 20669.29, 0.86, 0.447 }, - { 23622.05, 0.84, 0.394 }, - { 26574.80, 0.82, 0.347 }, - { 29527.56, 0.80, 0.304 }, - { 32480.31, 0.78, 0.266 }, - { 35433.07, 0.76, 0.231 }, - { 38385.83, 0.75, 0.201 }, - { 41338.58, 0.75, 0.174 }, - { 44291.34, 0.75, 0.151 }, - { 47244.09, 0.75, 0.131 }, - { 50196.85, 0.75, 0.114 }, - { 53149.61, 0.75, 0.099 }, - { 56102.36, 0.75, 0.086 }, - { 59055.12, 0.75, 0.075 }, - { 62007.87, 0.75, 0.065 }, + { -3000.00, 1.021, 1.1133 }, + { 0.00, 1.000, 1.0000 }, + { 2952.76, 0.980, 0.8978 }, + { 5905.51, 0.959, 0.8042 }, + { 8858.27, 0.939, 0.7187 }, + { 11811.02, 0.919, 0.6407 }, + { 14763.78, 0.898, 0.5697 }, + { 17716.54, 0.878, 0.5052 }, + { 20669.29, 0.858, 0.4468 }, + { 23622.05, 0.838, 0.3940 }, + { 26574.80, 0.817, 0.3463 }, + { 29527.56, 0.797, 0.3034 }, + { 32480.31, 0.777, 0.2649 }, + { 35433.07, 0.756, 0.2305 }, + { 38385.83, 0.752, 0.2000 }, + { 41338.58, 0.752, 0.1736 }, + { 44291.34, 0.752, 0.1506 }, + { 47244.09, 0.752, 0.1307 }, + { 50196.85, 0.752, 0.1134 }, + { 53149.61, 0.752, 0.0984 }, + { 56102.36, 0.752, 0.0854 }, + { 59055.12, 0.752, 0.0741 }, + { 62007.87, 0.752, 0.0643 }, + { 65000.00, 0.752, 0.0557 }, + { 68000.00, 0.754, 0.0482 }, + { 71000.00, 0.758, 0.0418 }, + { 74000.00, 0.761, 0.0362 }, + { 77000.00, 0.764, 0.0314 }, + { 80000.00, 0.767, 0.0273 }, + { 83000.00, 0.770, 0.0237 }, + { 86000.00, 0.773, 0.0206 }, + { 89000.00, 0.777, 0.0179 }, + { 92000.00, 0.780, 0.0156 }, + { 95000.00, 0.783, 0.0135 }, + { 98000.00, 0.786, 0.0118 }, + { 101000.00, 0.789, 0.0103 }, { -1, -1, -1 } }; @@ -106,42 +108,62 @@ _setup_tables () atmosphere_data[i][2]); } } - +#endif //////////////////////////////////////////////////////////////////////// // Implementation of FGEnvironment. //////////////////////////////////////////////////////////////////////// +void FGEnvironment::_init() +{ + live_update = false; + elevation_ft = 0; + visibility_m = 32000; + temperature_sea_level_degc = 15; + temperature_degc = 15; + dewpoint_sea_level_degc = 5; // guess + dewpoint_degc = 5; + pressure_sea_level_inhg = 29.92; + pressure_inhg = 29.92; + density_slugft3 = 0; + turbulence_magnitude_norm = 0; + turbulence_rate_hz = 1; + wind_from_heading_deg = 0; + wind_speed_kt = 0; + wind_from_north_fps = 0; + wind_from_east_fps = 0; + wind_from_down_fps = 0; + altitude_half_to_sun_m = 1000; + altitude_tropo_top_m = 10000; +#ifdef USING_TABLES + _setup_tables(); +#endif + _recalc_density(); + _recalc_relative_humidity(); + live_update = true; +} + FGEnvironment::FGEnvironment() - : elevation_ft(0), - visibility_m(32000), - temperature_sea_level_degc(15), - temperature_degc(15), - dewpoint_sea_level_degc(5), // guess - dewpoint_degc(5), - pressure_sea_level_inhg(29.92), - pressure_inhg(29.92), - turbulence_magnitude_norm(0), - turbulence_rate_hz(1), - wind_from_heading_deg(0), - wind_speed_kt(0), - wind_from_north_fps(0), - wind_from_east_fps(0), - wind_from_down_fps(0) -{ - _setup_tables(); - _recalc_density(); +{ + _init(); } FGEnvironment::FGEnvironment (const FGEnvironment &env) { - FGEnvironment(); + _init(); copy(env); } FGEnvironment::~FGEnvironment() { + Untie(); +} + +FGEnvironment & FGEnvironment::operator = ( const FGEnvironment & other ) +{ + copy( other ); + return *this; } void @@ -161,6 +183,13 @@ FGEnvironment::copy (const FGEnvironment &env) wind_from_down_fps = env.wind_from_down_fps; turbulence_magnitude_norm = env.turbulence_magnitude_norm; turbulence_rate_hz = env.turbulence_rate_hz; + pressure_inhg = env.pressure_inhg; + density_slugft3 = env.density_slugft3; + density_tropo_avg_kgm3 = env.density_tropo_avg_kgm3; + relative_humidity = env.relative_humidity; + altitude_half_to_sun_m = env.altitude_half_to_sun_m; + altitude_tropo_top_m = env.altitude_tropo_top_m; + live_update = env.live_update; } static inline bool @@ -182,23 +211,36 @@ maybe_copy_value (FGEnvironment * env, const SGPropertyNode * node, void FGEnvironment::read (const SGPropertyNode * node) { + bool live_update = set_live_update( false ); maybe_copy_value(this, node, "visibility-m", &FGEnvironment::set_visibility_m); + maybe_copy_value(this, node, "elevation-ft", + &FGEnvironment::set_elevation_ft); + if (!maybe_copy_value(this, node, "temperature-sea-level-degc", - &FGEnvironment::set_temperature_sea_level_degc)) - maybe_copy_value(this, node, "temperature-degc", - &FGEnvironment::set_temperature_degc); + &FGEnvironment::set_temperature_sea_level_degc)) { + if( maybe_copy_value(this, node, "temperature-degc", + &FGEnvironment::set_temperature_degc)) { + _recalc_sl_temperature(); + } + } if (!maybe_copy_value(this, node, "dewpoint-sea-level-degc", - &FGEnvironment::set_dewpoint_sea_level_degc)) - maybe_copy_value(this, node, "dewpoint-degc", - &FGEnvironment::set_dewpoint_degc); + &FGEnvironment::set_dewpoint_sea_level_degc)) { + if( maybe_copy_value(this, node, "dewpoint-degc", + &FGEnvironment::set_dewpoint_degc)) { + _recalc_sl_dewpoint(); + } + } if (!maybe_copy_value(this, node, "pressure-sea-level-inhg", - &FGEnvironment::set_pressure_sea_level_inhg)) - maybe_copy_value(this, node, "pressure-inhg", - &FGEnvironment::set_pressure_inhg); + &FGEnvironment::set_pressure_sea_level_inhg)) { + if( maybe_copy_value(this, node, "pressure-inhg", + &FGEnvironment::set_pressure_inhg)) { + _recalc_sl_pressure(); + } + } maybe_copy_value(this, node, "wind-from-heading-deg", &FGEnvironment::set_wind_from_heading_deg); @@ -206,16 +248,109 @@ FGEnvironment::read (const SGPropertyNode * node) maybe_copy_value(this, node, "wind-speed-kt", &FGEnvironment::set_wind_speed_kt); - maybe_copy_value(this, node, "elevation-ft", - &FGEnvironment::set_elevation_ft); - maybe_copy_value(this, node, "turbulence/magnitude-norm", &FGEnvironment::set_turbulence_magnitude_norm); maybe_copy_value(this, node, "turbulence/rate-hz", &FGEnvironment::set_turbulence_rate_hz); + + // calculate derived properties here to avoid duplicate expensive computations + _recalc_ne(); + _recalc_alt_pt(); + _recalc_alt_dewpoint(); + _recalc_density(); + _recalc_relative_humidity(); + + set_live_update(live_update); } +void FGEnvironment::Tie( SGPropertyNode_ptr base, bool archivable ) +{ + _tiedProperties.setRoot( base ); + + _tiedProperties.Tie( "visibility-m", this, + &FGEnvironment::get_visibility_m, + &FGEnvironment::set_visibility_m); + + _tiedProperties.Tie("temperature-sea-level-degc", this, + &FGEnvironment::get_temperature_sea_level_degc, + &FGEnvironment::set_temperature_sea_level_degc); + + _tiedProperties.Tie("temperature-degc", this, + &FGEnvironment::get_temperature_degc, + &FGEnvironment::set_temperature_degc); + + _tiedProperties.Tie("dewpoint-sea-level-degc", this, + &FGEnvironment::get_dewpoint_sea_level_degc, + &FGEnvironment::set_dewpoint_sea_level_degc); + + _tiedProperties.Tie("dewpoint-degc", this, + &FGEnvironment::get_dewpoint_degc, + &FGEnvironment::set_dewpoint_degc); + + _tiedProperties.Tie("pressure-sea-level-inhg", this, + &FGEnvironment::get_pressure_sea_level_inhg, + &FGEnvironment::set_pressure_sea_level_inhg); + + _tiedProperties.Tie("pressure-inhg", this, + &FGEnvironment::get_pressure_inhg, + &FGEnvironment::set_pressure_inhg); + + _tiedProperties.Tie("atmosphere/altitude-half-to-sun", this, + &FGEnvironment::get_altitude_half_to_sun_m, + &FGEnvironment::set_altitude_half_to_sun_m); + + _tiedProperties.Tie("atmosphere/altitude-troposphere-top", this, + &FGEnvironment::get_altitude_tropo_top_m, + &FGEnvironment::set_altitude_tropo_top_m); + + _tiedProperties.Tie("wind-from-heading-deg", this, + &FGEnvironment::get_wind_from_heading_deg, + &FGEnvironment::set_wind_from_heading_deg); + + _tiedProperties.Tie("wind-speed-kt", this, + &FGEnvironment::get_wind_speed_kt, + &FGEnvironment::set_wind_speed_kt); + + _tiedProperties.Tie("wind-from-north-fps", this, + &FGEnvironment::get_wind_from_north_fps, + &FGEnvironment::set_wind_from_north_fps); + + _tiedProperties.Tie("wind-from-east-fps", this, + &FGEnvironment::get_wind_from_east_fps, + &FGEnvironment::set_wind_from_east_fps); + + _tiedProperties.Tie("wind-from-down-fps", this, + &FGEnvironment::get_wind_from_down_fps, + &FGEnvironment::set_wind_from_down_fps); + + _tiedProperties.Tie("turbulence/magnitude-norm", this, + &FGEnvironment::get_turbulence_magnitude_norm, + &FGEnvironment::set_turbulence_magnitude_norm); + + _tiedProperties.Tie("turbulence/rate-hz", this, + &FGEnvironment::get_turbulence_rate_hz, + &FGEnvironment::set_turbulence_rate_hz); + + _tiedProperties.setAttribute( SGPropertyNode::ARCHIVE, archivable ); + + _tiedProperties.Tie("temperature-degf", this, + &FGEnvironment::get_temperature_degf); + + _tiedProperties.Tie("density-slugft3", this, + &FGEnvironment::get_density_slugft3); // read-only + + _tiedProperties.Tie("relative-humidity", this, + &FGEnvironment::get_relative_humidity); //ro + + _tiedProperties.Tie("atmosphere/density-tropo-avg", this, + &FGEnvironment::get_density_tropo_avg_kgm3); //ro +} + +void FGEnvironment::Untie() +{ + _tiedProperties.Untie(); +} double FGEnvironment::get_visibility_m () const @@ -271,6 +406,30 @@ FGEnvironment::get_density_slugft3 () const return density_slugft3; } +double +FGEnvironment::get_relative_humidity () const +{ + return relative_humidity; +} + +double +FGEnvironment::get_density_tropo_avg_kgm3 () const +{ + return density_tropo_avg_kgm3; +} + +double +FGEnvironment::get_altitude_half_to_sun_m () const +{ + return altitude_half_to_sun_m; +} + +double +FGEnvironment::get_altitude_tropo_top_m () const +{ + return altitude_tropo_top_m; +} + double FGEnvironment::get_wind_from_heading_deg () const { @@ -304,9 +463,6 @@ FGEnvironment::get_wind_from_down_fps () const double FGEnvironment::get_turbulence_magnitude_norm () const { - if( sgEnviro.get_turbulence_enable_state() ) - if (fgGetBool("/environment/params/real-world-weather-fetch") == true) - return sgEnviro.get_cloud_turbulence(); return turbulence_magnitude_norm; } @@ -334,16 +490,23 @@ FGEnvironment::set_temperature_sea_level_degc (double t) temperature_sea_level_degc = t; if (dewpoint_sea_level_degc > t) dewpoint_sea_level_degc = t; - _recalc_alt_temperature(); - _recalc_density(); + if( live_update ) { + _recalc_alt_pt(); + _recalc_density(); + } } void FGEnvironment::set_temperature_degc (double t) { temperature_degc = t; - _recalc_sl_temperature(); - _recalc_density(); + if( live_update ) { + _recalc_sl_temperature(); + _recalc_sl_pressure(); + _recalc_alt_pt(); + _recalc_density(); + _recalc_relative_humidity(); + } } void @@ -352,67 +515,86 @@ FGEnvironment::set_dewpoint_sea_level_degc (double t) dewpoint_sea_level_degc = t; if (temperature_sea_level_degc < t) temperature_sea_level_degc = t; - _recalc_alt_dewpoint(); - _recalc_density(); + if( live_update ) { + _recalc_alt_dewpoint(); + _recalc_density(); + } } void FGEnvironment::set_dewpoint_degc (double t) { dewpoint_degc = t; - _recalc_sl_dewpoint(); - _recalc_density(); + if( live_update ) { + _recalc_sl_dewpoint(); + _recalc_density(); + _recalc_relative_humidity(); + } } void FGEnvironment::set_pressure_sea_level_inhg (double p) { pressure_sea_level_inhg = p; - _recalc_alt_pressure(); - _recalc_density(); + if( live_update ) { + _recalc_alt_pt(); + _recalc_density(); + } } void FGEnvironment::set_pressure_inhg (double p) { pressure_inhg = p; - _recalc_sl_pressure(); - _recalc_density(); + if( live_update ) { + _recalc_sl_pressure(); + _recalc_density(); + } } void FGEnvironment::set_wind_from_heading_deg (double h) { wind_from_heading_deg = h; - _recalc_ne(); + if( live_update ) { + _recalc_ne(); + } } void FGEnvironment::set_wind_speed_kt (double s) { wind_speed_kt = s; - _recalc_ne(); + if( live_update ) { + _recalc_ne(); + } } void FGEnvironment::set_wind_from_north_fps (double n) { wind_from_north_fps = n; - _recalc_hdgspd(); + if( live_update ) { + _recalc_hdgspd(); + } } void FGEnvironment::set_wind_from_east_fps (double e) { wind_from_east_fps = e; - _recalc_hdgspd(); + if( live_update ) { + _recalc_hdgspd(); + } } void FGEnvironment::set_wind_from_down_fps (double d) { wind_from_down_fps = d; - _recalc_hdgspd(); + if( live_update ) { + _recalc_hdgspd(); + } } void @@ -431,43 +613,45 @@ void FGEnvironment::set_elevation_ft (double e) { elevation_ft = e; - _recalc_alt_temperature(); - _recalc_alt_dewpoint(); - _recalc_alt_pressure(); - _recalc_density(); + if( live_update ) { + _recalc_alt_pt(); + _recalc_alt_dewpoint(); + _recalc_density(); + _recalc_relative_humidity(); + } } void -FGEnvironment::_recalc_hdgspd () +FGEnvironment::set_altitude_half_to_sun_m (double alt) { - double angle_rad; + altitude_half_to_sun_m = alt; + if( live_update ) { + _recalc_density_tropo_avg_kgm3(); + } +} - if (wind_from_east_fps == 0) { - angle_rad = (wind_from_north_fps >= 0 ? SGD_PI_2 : -SGD_PI_2); - } else { - angle_rad = atan(wind_from_north_fps/wind_from_east_fps); +void +FGEnvironment::set_altitude_tropo_top_m (double alt) +{ + altitude_tropo_top_m = alt; + if( live_update ) { + _recalc_density_tropo_avg_kgm3(); } - wind_from_heading_deg = angle_rad * SGD_RADIANS_TO_DEGREES; - if (wind_from_east_fps >= 0) - wind_from_heading_deg = 90 - wind_from_heading_deg; - else - wind_from_heading_deg = 270 - wind_from_heading_deg; +} + + +void +FGEnvironment::_recalc_hdgspd () +{ + wind_from_heading_deg = + atan2(wind_from_east_fps, wind_from_north_fps) * SGD_RADIANS_TO_DEGREES; + + if( wind_from_heading_deg < 0 ) + wind_from_heading_deg += 360.0; -#if 0 - // FIXME: Windspeed can become negative with these formulas. - // which can cause problems for animations that rely - // on the windspeed property. - if (angle_rad == 0) - wind_speed_kt = fabs(wind_from_east_fps - * SG_METER_TO_NM * SG_FEET_TO_METER * 3600); - else - wind_speed_kt = (wind_from_north_fps / sin(angle_rad)) - * SG_METER_TO_NM * SG_FEET_TO_METER * 3600; -#else wind_speed_kt = sqrt(wind_from_north_fps * wind_from_north_fps + wind_from_east_fps * wind_from_east_fps) * SG_METER_TO_NM * SG_FEET_TO_METER * 3600; -#endif } void @@ -482,28 +666,34 @@ FGEnvironment::_recalc_ne () sin(wind_from_heading_deg * SGD_DEGREES_TO_RADIANS); } +// Intended to help with the interpretation of METAR data, +// not for random in-flight outside-air temperatures. void FGEnvironment::_recalc_sl_temperature () { - // If we're in the stratosphere, leave sea-level temp alone - if (elevation_ft < 38000) { - temperature_sea_level_degc = - (temperature_degc + 273.15) - /_temperature_degc_table->interpolate(elevation_ft) - - 273.15; + +#if 0 + { + SG_LOG(SG_ENVIRONMENT, SG_DEBUG, "recalc_sl_temperature: using " + << temperature_degc << " @ " << elevation_ft << " :: " << this); } -} +#endif -void -FGEnvironment::_recalc_alt_temperature () -{ - if (elevation_ft < 38000) { - temperature_degc = - (temperature_sea_level_degc + 273.15) * - _temperature_degc_table->interpolate(elevation_ft) - 273.15; - } else { - temperature_degc = -56.49; // Stratosphere is constant + if (elevation_ft * atmodel::foot >= ISA_def[1].height) { + SG_LOG(SG_ENVIRONMENT, SG_ALERT, "recalc_sl_temperature: " + << "valid only in troposphere, not " << elevation_ft); + return; } + +// Clamp: temperature of the stratosphere, in degrees C: + double t_strato = ISA_def[1].temp - atmodel::freezing; + if (temperature_degc < t_strato) temperature_sea_level_degc = t_strato; + else temperature_sea_level_degc = + temperature_degc + elevation_ft * atmodel::foot * ISA_def[0].lapse; + +// Alternative implemenation: +// else temperature_sea_level_inhg = T_layer(0., elevation_ft * foot, +// pressure_inhg * inHg, temperature_degc + freezing, ISA_def[0].lapse) - freezing; } void @@ -531,15 +721,45 @@ FGEnvironment::_recalc_alt_dewpoint () void FGEnvironment::_recalc_sl_pressure () { - pressure_sea_level_inhg = - pressure_inhg / _pressure_inhg_table->interpolate(elevation_ft); + using namespace atmodel; +#if 0 + { + SG_LOG(SG_ENVIRONMENT, SG_ALERT, "recalc_sl_pressure: using " + << pressure_inhg << " and " + << temperature_degc << " @ " << elevation_ft << " :: " << this); + } +#endif + pressure_sea_level_inhg = P_layer(0., elevation_ft * foot, + pressure_inhg * inHg, temperature_degc + freezing, ISA_def[0].lapse) / inHg; } +// This gets called at frame rate, to account for the aircraft's +// changing altitude. +// Called by set_elevation_ft() which is called by FGEnvironmentMgr::update + void -FGEnvironment::_recalc_alt_pressure () +FGEnvironment::_recalc_alt_pt () { - pressure_inhg = - pressure_sea_level_inhg * _pressure_inhg_table->interpolate(elevation_ft); + using namespace atmodel; +#if 0 + { + static int count(0); + if (++count % 1000 == 0) { + SG_LOG(SG_ENVIRONMENT, SG_ALERT, + "recalc_alt_pt for: " << elevation_ft + << " using " << pressure_sea_level_inhg + << " and " << temperature_sea_level_degc + << " :: " << this + << " # " << count); + } + } +#endif + double press = pressure_inhg * inHg; + double temp = temperature_degc + freezing; + boost::tie(press, temp) = PT_vs_hpt(elevation_ft * foot, + pressure_sea_level_inhg * inHg, temperature_sea_level_degc + freezing); + temperature_degc = temp - freezing; + pressure_inhg = press / inHg; } void @@ -558,10 +778,52 @@ FGEnvironment::_recalc_density () double virtual_temperature_degr = virtual_temperature_degk * 1.8; density_slugft3 = pressure_psf / (virtual_temperature_degr * 1718); + _recalc_density_tropo_avg_kgm3(); +} + +// This is used to calculate the average density on the path +// of sunlight to the observer for calculating sun-color +void +FGEnvironment::_recalc_density_tropo_avg_kgm3 () +{ + double pressure_mb = pressure_inhg * 33.86; + double vaporpressure = 6.11 * pow(10.0, ((7.5 * dewpoint_degc) / (237.7 + dewpoint_degc))); + + double virtual_temp = (temperature_degc + 273.15) / (1 - 0.379 * (vaporpressure/pressure_mb)); + + double density_half = (100 * pressure_mb * exp(-altitude_half_to_sun_m / 8000)) + / (287.05 * virtual_temp); + double density_tropo = (100 * pressure_mb * exp((-1 * altitude_tropo_top_m) / 8000)) + / ( 287.05 * virtual_temp); + + density_tropo_avg_kgm3 = ((density_slugft3 * 515.379) + density_half + density_tropo) / 3; +} + +void +FGEnvironment::_recalc_relative_humidity () +{ +/* + double vaporpressure = 6.11 * pow(10.0, ((7.5 * dewpoint_degc) / ( 237.7 + dewpoint_degc))); + double sat_vaporpressure = 6.11 * pow(10.0, ((7.5 * temperature_degc) + / ( 237.7 + temperature_degc)) ); + relative_humidity = 100 * vaporpressure / sat_vaporpressure ; + + with a little algebra, this gets the same result and spares two multiplications and one pow() +*/ + double a = (7.5 * dewpoint_degc) / ( 237.7 + dewpoint_degc); + double b = (7.5 * temperature_degc) / ( 237.7 + temperature_degc); + relative_humidity = 100 * pow(10.0,a-b); +} + +bool +FGEnvironment::set_live_update( bool _live_update ) +{ + bool b = live_update; + live_update = _live_update; + return b; } - //////////////////////////////////////////////////////////////////////// // Functions. //////////////////////////////////////////////////////////////////////// @@ -587,54 +849,69 @@ do_interp_deg (double a, double b, double fraction) return fmod(do_interp(a, b, fraction), 360); } -void -interpolate (const FGEnvironment * env1, const FGEnvironment * env2, - double fraction, FGEnvironment * result) +FGEnvironment & +FGEnvironment::interpolate( const FGEnvironment & env2, + double fraction, FGEnvironment * result) const { + // don't calculate each internal property every time we set a single value + // we trigger that at the end of the interpolation process + bool live_update = result->set_live_update( false ); + result->set_visibility_m - (do_interp(env1->get_visibility_m(), - env2->get_visibility_m(), + (do_interp(get_visibility_m(), + env2.get_visibility_m(), fraction)); result->set_temperature_sea_level_degc - (do_interp(env1->get_temperature_sea_level_degc(), - env2->get_temperature_sea_level_degc(), + (do_interp(get_temperature_sea_level_degc(), + env2.get_temperature_sea_level_degc(), fraction)); - result->set_dewpoint_degc - (do_interp(env1->get_dewpoint_sea_level_degc(), - env2->get_dewpoint_sea_level_degc(), + result->set_dewpoint_sea_level_degc + (do_interp(get_dewpoint_sea_level_degc(), + env2.get_dewpoint_sea_level_degc(), fraction)); result->set_pressure_sea_level_inhg - (do_interp(env1->get_pressure_sea_level_inhg(), - env2->get_pressure_sea_level_inhg(), + (do_interp(get_pressure_sea_level_inhg(), + env2.get_pressure_sea_level_inhg(), fraction)); result->set_wind_from_heading_deg - (do_interp_deg(env1->get_wind_from_heading_deg(), - env2->get_wind_from_heading_deg(), + (do_interp_deg(get_wind_from_heading_deg(), + env2.get_wind_from_heading_deg(), fraction)); result->set_wind_speed_kt - (do_interp(env1->get_wind_speed_kt(), - env2->get_wind_speed_kt(), + (do_interp(get_wind_speed_kt(), + env2.get_wind_speed_kt(), fraction)); result->set_elevation_ft - (do_interp(env1->get_elevation_ft(), - env2->get_elevation_ft(), + (do_interp(get_elevation_ft(), + env2.get_elevation_ft(), fraction)); result->set_turbulence_magnitude_norm - (do_interp(env1->get_turbulence_magnitude_norm(), - env2->get_turbulence_magnitude_norm(), + (do_interp(get_turbulence_magnitude_norm(), + env2.get_turbulence_magnitude_norm(), fraction)); result->set_turbulence_rate_hz - (do_interp(env1->get_turbulence_rate_hz(), - env2->get_turbulence_rate_hz(), + (do_interp(get_turbulence_rate_hz(), + env2.get_turbulence_rate_hz(), fraction)); + + // calculate derived properties here to avoid duplicate expensive computations + result->_recalc_ne(); + result->_recalc_alt_pt(); + result->_recalc_alt_dewpoint(); + result->_recalc_density(); + result->_recalc_relative_humidity(); + + result->set_live_update(live_update); + + return *result; } // end of environment.cxx