Clean up the code, impement relative humidity (and related to that dew point) and better implement arid climates
This commit is contained in:
parent
1ae2e4c4cd
commit
3384a85650
2 changed files with 270 additions and 186 deletions
|
@ -34,8 +34,18 @@
|
|||
#include "climate.hxx"
|
||||
|
||||
// Based on "World Map of the Köppen-Geiger climate classification"
|
||||
// The map is provided with a spatial resolution of 0.5 degree (3km).
|
||||
// The map is provided with a spatial resolution of approx. 10x10km per pixel.
|
||||
// http://koeppen-geiger.vu-wien.ac.at/present.htm
|
||||
//
|
||||
// References:
|
||||
// * Teuling, A. J.: Technical note: Towards a continuous classification of
|
||||
// climate usingbivariate colour mapping, Hydrol. Earth Syst. Sci., 15,
|
||||
// 3071–3075, https://doi.org/10.5194/hess-15-3071-2011, 2011.
|
||||
//
|
||||
// * Lawrence, Mark G., 2005: The relationship between relative humidity and
|
||||
// the dewpoint temperature in moist air: A simple conversion and
|
||||
// applications. Bull. Amer. Meteor. Soc., 86, 225-233.
|
||||
// doi: http://dx.doi.org/10.1175/BAMS-86-2-225
|
||||
|
||||
FGClimate::FGClimate(const SGGeod& position)
|
||||
{
|
||||
|
@ -75,11 +85,11 @@ void FGClimate::update(const SGGeod& position)
|
|||
if (fabs(_prev_lat - _adj_latitude_deg) > _epsilon ||
|
||||
fabs(_prev_lon - _adj_longitude_deg) > _epsilon)
|
||||
{
|
||||
_autumn = false;
|
||||
_is_autumn = false;
|
||||
if ((latitude_deg*_sun_latitude_deg < 0.0) // autumn + spring
|
||||
&& (_adj_latitude_deg > _prev_lat)) // autumn
|
||||
{
|
||||
_autumn = true;
|
||||
_is_autumn = true;
|
||||
}
|
||||
|
||||
_prev_lat = _adj_latitude_deg;
|
||||
|
@ -88,20 +98,22 @@ void FGClimate::update(const SGGeod& position)
|
|||
update_day_factor();
|
||||
update_season_factor();
|
||||
|
||||
// from lat/lon to screen coordinates
|
||||
double x = 180.0 + longitude_deg;
|
||||
double y = 90.0 + latitude_deg;
|
||||
|
||||
_col = static_cast<int>(x * _image_width/360.0);
|
||||
_row = static_cast<int>(y * _image_height/180.0);
|
||||
|
||||
osg::Vec4f color;
|
||||
if (image) {
|
||||
color = image->getColor(_col, _row);
|
||||
if (image)
|
||||
{
|
||||
// from lat/lon to screen coordinates
|
||||
double x = 180.0 + longitude_deg;
|
||||
double y = 90.0 + latitude_deg;
|
||||
double s, t;
|
||||
|
||||
s = static_cast<int>(x * static_cast<double>(_image_width)/360.0);
|
||||
t = static_cast<int>(y * static_cast<double>(_image_height)/180.0);
|
||||
|
||||
color = image->getColor(s, t);
|
||||
}
|
||||
|
||||
// convert from color shades to koppen-classicfication
|
||||
_classicfication = static_cast<int>( 255.0*color[0]/4.0 );
|
||||
_classicfication = static_cast<int>( 255.0f*color[0]/4.0f );
|
||||
|
||||
if (_classicfication == 0) set_ocean();
|
||||
else if (_classicfication < 5) set_tropical();
|
||||
|
@ -111,6 +123,9 @@ void FGClimate::update(const SGGeod& position)
|
|||
else if (_classicfication < 32) set_polar();
|
||||
else set_ocean();
|
||||
|
||||
// Mark G. Lawrence:
|
||||
_dew_point = _temperature_gl - ((100.0 - 100.0*_relative_humidity)/5.0);
|
||||
|
||||
set_environment();
|
||||
|
||||
#if REPORT_TO_CONSOLE
|
||||
|
@ -119,31 +134,27 @@ void FGClimate::update(const SGGeod& position)
|
|||
}
|
||||
}
|
||||
|
||||
// returns 0.0 for night up to 1.0 for noon
|
||||
// _day_noon returns 0.0 for night up to 1.0 for noon
|
||||
void FGClimate::update_day_factor()
|
||||
{
|
||||
// noon is when lon == 180.0
|
||||
_day_noon = fabs(_adj_longitude_deg - 180.0)/180.0;
|
||||
}
|
||||
|
||||
// The seasons are currently based purely on where the sun's perpendicular
|
||||
// (perp.) rays strike the earth. Winter (perp. Rays moving from 23.5 S to
|
||||
// equator), Spring (perp. Rays moving from the equator to 23.5 N), Summer
|
||||
// (perp. Rays moving from 23.5 N to equator) and Fall (perp. Rays moving
|
||||
// from equator to 23.5 S).
|
||||
// returns 0.0 for winter up to 1.0 for summer
|
||||
// _season_summer returns 0.0 for winter up to 1.0 for summer
|
||||
// _season_transistional returns 0.0 for early autumn/late spring up to
|
||||
// 1.0 for late autumn/early spring
|
||||
// to distinguish between the two use the _autumn flag.
|
||||
void FGClimate::update_season_factor()
|
||||
{
|
||||
double latitude_deg = pos.getLatitudeDeg();
|
||||
double sign = latitude_deg >= 0.0 ? 1.0 : -1.0; // hemisphere
|
||||
|
||||
_season_summer = (23.5 + sign*_sun_latitude_deg)/(2.0*23.5);
|
||||
|
||||
_season_winter = 2.0*(1.0 - _season_summer) - 1.0;
|
||||
if (_season_winter < 0.0) _season_winter = 0.0;
|
||||
else if (_season_winter > 1.0) _season_winter = 1.0;
|
||||
|
||||
double fact_lat = 6.0 - 12.0*fabs(latitude_deg)/90.0;
|
||||
_season_winter *= (0.5 - 0.5*sin(atan(SGD_2PI*fact_lat)));
|
||||
_season_transistional = 2.0*(1.0 - _season_summer) - 1.0;
|
||||
if (_season_transistional < 0.0) _season_transistional = 0.0;
|
||||
else if (_season_transistional > 1.0) _season_transistional = 1.0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -179,6 +190,9 @@ void FGClimate::set_ocean()
|
|||
// steady winds
|
||||
_wind = 3.0;
|
||||
|
||||
// no autumn
|
||||
_has_autumn = false;
|
||||
|
||||
// average precipitation
|
||||
_total_annual_precipitation = 990.0; // global
|
||||
double avg_precipitation = 100.0 - (_total_annual_precipitation/25.0);
|
||||
|
@ -191,50 +205,62 @@ void FGClimate::set_tropical()
|
|||
{
|
||||
// weather
|
||||
_total_annual_precipitation = 3000.0;
|
||||
// double avg_precipitation = 100.0 - (_total_annual_precipitation/25.0);
|
||||
|
||||
double day = _day_noon;
|
||||
|
||||
double summer = _season_summer;
|
||||
double winter = 1.0 - summer;
|
||||
|
||||
double temp_equator_max = 31.0;
|
||||
double temp_equator_min = 23.0;
|
||||
double temp_equator = season_even(day, temp_equator_min, temp_equator_max);
|
||||
|
||||
// winter temperatures are three-quarter of the summer temperatures
|
||||
_temperature_sl = season_even(summer, 0.75*temp_equator, temp_equator);
|
||||
_temperature_gl = _temperature_sl;
|
||||
|
||||
// relative humidity based on latitude
|
||||
double latitude_deg = pos.getLatitudeDeg();
|
||||
double fact_lat = fabs(latitude_deg)/90.0;
|
||||
_relative_humidity = season_even(fact_lat, 0.1, 0.8);
|
||||
|
||||
// wind based on latitude (0.0 - 15 degrees)
|
||||
fact_lat = std::max(abs(latitude_deg), 15.0)/15.0;
|
||||
_wind = 3.0*fact_lat*fact_lat;
|
||||
double latitude_deg = pos.getLatitudeDeg();
|
||||
double fact_lat = std::max(abs(latitude_deg), 15.0)/15.0;
|
||||
double wind = 3.0*fact_lat*fact_lat;
|
||||
|
||||
double temp_night = _temperature_sl;
|
||||
double temp_day = _temperature_sl;
|
||||
double precipitation = _precipitation;
|
||||
double relative_humidity = _relative_humidity;
|
||||
switch(_classicfication)
|
||||
{
|
||||
case 1: // Af: equatorial, fully humid
|
||||
_precipitation = season_even(winter, 150.0, 280.0);
|
||||
temp_night = triangular(summer, 20.0, 22.5);
|
||||
temp_day = triangular(summer, 29.5, 32.5);
|
||||
precipitation = season_even(winter, 150.0, 280.0);
|
||||
relative_humidity = season_even(summer, 0.75, 0.85);
|
||||
break;
|
||||
case 2: // Am: equatorial, monsoonal
|
||||
_precipitation = season_even(summer, 75.0, 320.0);
|
||||
_wind *= 2.0*_precipitation/320.0;
|
||||
temp_night = triangular(summer, 17.5, 22.5);
|
||||
temp_day = triangular(summer, 27.5, 32.5);
|
||||
precipitation = season_even(summer, 75.0, 320.0);
|
||||
relative_humidity = season_even(summer, 0.75, 0.85);
|
||||
wind *= 2.0*_precipitation/320.0;
|
||||
break;
|
||||
case 3: // As: equatorial, summer dry
|
||||
_precipitation = season_even(0.5*summer + 0.5 - 0.5*_season_winter , 35.0, 150.0);
|
||||
_wind *= 2.0*_precipitation/350.0;
|
||||
temp_night = season_long_high(summer, 15.0, 22.5);
|
||||
temp_day = triangular(summer, 27.5, 35.0);
|
||||
precipitation = season_even(0.5*summer + 0.5 - 0.5*_season_transistional , 35.0, 150.0);
|
||||
relative_humidity = season_even(summer, 0.60, 0.80);
|
||||
wind *= 2.0*_precipitation/350.0;
|
||||
break;
|
||||
case 4: // Aw: equatorial, winter dry
|
||||
_precipitation = season_even(summer, 10.0, 230.0);
|
||||
_wind *= 2.0*_precipitation/230.0;
|
||||
temp_night = season_long_high(summer, 15.0, 22.5);
|
||||
temp_day = triangular(summer, 27.5, 35.0);
|
||||
precipitation = season_even(summer, 10.0, 230.0);
|
||||
relative_humidity = season_even(summer, 0.60, 0.80);
|
||||
wind *= 2.0*_precipitation/230.0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_temperature_gl = season_even(day, temp_night, temp_day);
|
||||
_temperature_mean = 0.5*(temp_night + temp_day);
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
_relative_humidity = relative_humidity;
|
||||
_precipitation = precipitation;
|
||||
_has_autumn = false;
|
||||
_wind = wind;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Desert_climate
|
||||
|
@ -242,42 +268,55 @@ void FGClimate::set_tropical()
|
|||
void FGClimate::set_dry()
|
||||
{
|
||||
double day = _day_noon;
|
||||
|
||||
double summer = _season_summer;
|
||||
double winter = 1.0 - summer;
|
||||
|
||||
double temp_mean_summer = 32.0;
|
||||
double temp_day_summer = 41.0;
|
||||
double temp_night_summer = 2.0*temp_mean_summer - temp_day_summer;
|
||||
double temp_day_winter = temp_day_summer - temp_night_summer;
|
||||
double temp_night_winter = 0.0;
|
||||
|
||||
double temp_winter = season_even(day, temp_night_winter, temp_day_winter);
|
||||
double temp_summer = season_even(day, temp_night_summer, temp_day_summer);
|
||||
_temperature_gl = season_even(summer, temp_winter, temp_summer);
|
||||
|
||||
if (_classicfication == 6 || _classicfication == 8) { // cold arid
|
||||
_temperature_mean -= 14.0;
|
||||
_temperature_gl -= 14.0;
|
||||
}
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
double temp_mean_winter = 0.5*(temp_day_winter + temp_night_winter);
|
||||
_temperature_mean = season_even(summer, temp_mean_winter, temp_mean_summer);
|
||||
|
||||
// low relative humidity
|
||||
_relative_humidity = 0.25;
|
||||
|
||||
// steady winds
|
||||
_wind = 3.0;
|
||||
|
||||
_total_annual_precipitation = 100.0;
|
||||
if (_classicfication == 5 || _classicfication == 6) { // steppe
|
||||
_total_annual_precipitation *= 2.0;
|
||||
}
|
||||
|
||||
double avg_precipitation = _total_annual_precipitation/12.0;
|
||||
_precipitation = winter*2.0*avg_precipitation;
|
||||
double temp_night = _temperature_sl;
|
||||
double temp_day = _temperature_sl;
|
||||
double precipitation = _precipitation;
|
||||
double relative_humidity = _relative_humidity;
|
||||
switch(_classicfication)
|
||||
{
|
||||
case 5: // BSh: arid, steppe, hot arid
|
||||
temp_night = season_long_high(summer, 10.0, 22.0);
|
||||
temp_day = triangular(summer, 27.5, 35.0);
|
||||
precipitation = season_long_low(summer, 8.0, 117.0);
|
||||
relative_humidity = season_long_low(summer, 0.20, 0.30);
|
||||
break;
|
||||
case 6: // BSk: arid, steppe, cold arid
|
||||
temp_night = season_even(summer, -14.0, 12.0);
|
||||
temp_day = season_even(summer, 0.0, 30.0);
|
||||
precipitation = season_even(summer, 15.0, 34.0);
|
||||
relative_humidity = season_even(summer, 0.48, 0.67);
|
||||
break;
|
||||
case 7: // BWh: arid, desert, hot arid
|
||||
temp_night = season_even(summer, 7.5, 22.0);
|
||||
temp_day = season_even(summer, 22.5, 37.5);
|
||||
precipitation = monsoonal(summer, 3.0, 18.0);
|
||||
relative_humidity = monsoonal(summer, 0.25, 0.55);
|
||||
break;
|
||||
case 8: // BWk: arid, desert, cold arid
|
||||
temp_night = season_even(summer, -15.0, 15.0);
|
||||
temp_day = season_even(summer, -2.0, 30.0);
|
||||
precipitation = linear(summer, 4.0, 14.0);
|
||||
relative_humidity = linear(summer, 0.45, 0.61);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_temperature_gl = season_even(day, temp_night, temp_day);
|
||||
_temperature_mean = 0.5*(temp_night + temp_day);
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
_relative_humidity = relative_humidity;
|
||||
_precipitation = precipitation;
|
||||
_has_autumn = false;
|
||||
_wind = 3.0;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Temperate_climate
|
||||
|
@ -288,152 +327,177 @@ void FGClimate::set_temperate()
|
|||
double summer = _season_summer;
|
||||
double winter = 1.0 - summer;
|
||||
|
||||
double temp_min = _temperature_sl;
|
||||
double temp_max = _temperature_sl;
|
||||
double temp_night = _temperature_sl;
|
||||
double temp_day = _temperature_sl;
|
||||
double precipitation = _precipitation;
|
||||
double relative_humidity = _relative_humidity;
|
||||
switch(_classicfication)
|
||||
{
|
||||
case 9: // Cfa: warm temperature, fully humid hot summer
|
||||
temp_min = season_even(summer, -3.0, 20.0);
|
||||
temp_max = season_even(summer, 10.0, 33.0);
|
||||
temp_night = season_even(summer, -3.0, 20.0);
|
||||
temp_day = season_even(summer, 10.0, 33.0);
|
||||
precipitation = season_even(summer, 60.0, 123.0);
|
||||
relative_humidity = season_even(summer, 0.6, 0.9);
|
||||
relative_humidity = season_even(summer, 0.65, 0.80);
|
||||
break;
|
||||
case 10: // Cfb: warm temperature, fully humid, warm summer
|
||||
temp_min = season_even(summer, -3.0, 10.0);
|
||||
temp_max = season_even(summer, 5.0, 25.0);
|
||||
precipitation = linear(0.5*(summer + _season_winter), 44.0, 88.0);
|
||||
relative_humidity = 0.8;
|
||||
temp_night = season_even(summer, -3.0, 10.0);
|
||||
temp_day = season_even(summer, 5.0, 25.0);
|
||||
precipitation = linear(0.5*(summer+_season_transistional), 44.0, 88.0);
|
||||
relative_humidity = season_even(summer, 0.68, 0.87);
|
||||
break;
|
||||
case 11: // Cfc: warm temperature, fully humid, cool summer
|
||||
temp_min = season_long_low(summer, -3.0, 8.0);
|
||||
temp_max = season_long_low(summer, 2.0, 14.0);
|
||||
temp_night = season_long_low(summer, -3.0, 8.0);
|
||||
temp_day = season_long_low(summer, 2.0, 14.0);
|
||||
precipitation = season_even(winter, 44.0, 88.0);
|
||||
relative_humidity = 0.8;
|
||||
relative_humidity = season_even(summer, 0.70, 0.85);
|
||||
break;
|
||||
case 12: // Csa: warm temperature, summer dry, hot summer
|
||||
temp_min = season_even(summer, 2.0, 16.0);
|
||||
temp_max = season_even(summer, 12.0, 33.0);
|
||||
precipitation = season_long_low(summer, 25.0, 70.0);
|
||||
temp_night = season_even(summer, 2.0, 16.0);
|
||||
temp_day = season_even(summer, 12.0, 33.0);
|
||||
precipitation = season_long_low(winter, 25.0, 70.0);
|
||||
relative_humidity = season_even(winter, 0.58, 0.72);
|
||||
break;
|
||||
case 13: // Csb: warm temperature, summer dry, warm summer
|
||||
temp_min = linear(summer, -4.0, 10.0);
|
||||
temp_max = linear(summer, 6.0, 27.0);
|
||||
temp_night = linear(summer, -4.0, 10.0);
|
||||
temp_day = linear(summer, 6.0, 27.0);
|
||||
precipitation = season_short(winter, 25.0, 120.0);
|
||||
relative_humidity = season_even(winter, 0.50, 0.72);
|
||||
break;
|
||||
case 14: // Csc: warm temperature, summer dry, cool summer
|
||||
temp_min = season_even(summer, -4.0, 5.0);
|
||||
temp_max = season_even(summer, 5.0, 16.0);
|
||||
precipitation = season_even(summer, 60.0, 95.0);
|
||||
temp_night = season_even(summer, -4.0, 5.0);
|
||||
temp_day = season_even(summer, 5.0, 16.0);
|
||||
precipitation = season_even(winter, 60.0, 95.0);
|
||||
relative_humidity = season_even(winter, 0.55, 0.75);
|
||||
break;
|
||||
case 15: // Cwa: warm temperature, winter dry, hot summer
|
||||
temp_min = season_even(summer, 4.0, 20.0);
|
||||
temp_max = season_long_low(summer, 15.0, 30.0);
|
||||
temp_night = season_even(summer, 4.0, 20.0);
|
||||
temp_day = season_long_low(summer, 15.0, 30.0);
|
||||
precipitation = season_long_low(summer, 10.0, 320.0);
|
||||
relative_humidity = season_even(summer, 0.60, 0.79);
|
||||
break;
|
||||
case 16: // Cwb: warm temperature, winter dry, warm summer
|
||||
temp_min = season_even(summer, 1.0, 13.0);
|
||||
temp_max = season_long_low(summer, 15.0, 27.0);
|
||||
temp_night = season_even(summer, 1.0, 13.0);
|
||||
temp_day = season_long_low(summer, 15.0, 27.0);
|
||||
precipitation = season_long_low(summer, 10.0, 250.0);
|
||||
relative_humidity = season_even(summer, 0.58, 0.72);
|
||||
break;
|
||||
case 17: // Cwc: warm temperature, winter dry, cool summer
|
||||
temp_min = season_long_high(winter, -9.0, 6.0);
|
||||
temp_max = season_long_high(winter, 6.0, 17.0);
|
||||
temp_night = season_long_high(summer, -9.0, 6.0);
|
||||
temp_day = season_long_high(summer, 6.0, 17.0);
|
||||
precipitation = season_long_low(summer, 10.0, 200.0);
|
||||
relative_humidity = season_even(summer, 0.50, 0.58);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_temperature_gl = season_even(day, temp_min, temp_max);
|
||||
_temperature_gl = season_even(day, temp_night, temp_day);
|
||||
_temperature_mean = 0.5*(temp_night + temp_day);
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
_temperature_mean = 0.5*(temp_min + temp_max);
|
||||
_precipitation = precipitation;
|
||||
_relative_humidity = relative_humidity;
|
||||
_precipitation = precipitation;
|
||||
_has_autumn = true;
|
||||
_wind = 3.0;
|
||||
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Continental_climate
|
||||
void FGClimate::set_continetal()
|
||||
{
|
||||
double day = _day_noon;
|
||||
double summer = _season_summer;
|
||||
double winter = 1.0 - summer;
|
||||
|
||||
double temp_max = _temperature_sl;
|
||||
double temp_min = _temperature_sl;
|
||||
double temp_day = _temperature_sl;
|
||||
double temp_night = _temperature_sl;
|
||||
double precipitation = _precipitation;
|
||||
double relative_humidity = _relative_humidity;
|
||||
switch(_classicfication)
|
||||
{
|
||||
case 18: // Dfa: snow, fully humid, hot summer
|
||||
temp_min = season_even(summer, -15.0, 13.0);
|
||||
temp_max = season_even(summer, -5.0, 30.0);
|
||||
_precipitation = season_even(summer, 25.0, 65.0);
|
||||
temp_night = season_even(summer, -15.0, 13.0);
|
||||
temp_day = season_even(summer, -5.0, 30.0);
|
||||
precipitation = season_even(summer, 25.0, 65.0);
|
||||
relative_humidity = season_even(summer, 0.68, 0.72);
|
||||
break;
|
||||
case 19: // Dfb: snow, fully humid, warm summer, warm summer
|
||||
temp_min = season_even(summer, -17.5, 10.0);
|
||||
temp_max = season_even(summer, -7.5, 25.0);
|
||||
_precipitation = season_even(summer, 30.0, 70.0);
|
||||
temp_night = season_even(summer, -17.5, 10.0);
|
||||
temp_day = season_even(summer, -7.5, 25.0);
|
||||
precipitation = season_even(summer, 30.0, 70.0);
|
||||
relative_humidity = season_even(summer, 0.69, 0.81);
|
||||
break;
|
||||
case 20: // Dfc: snow, fully humid, cool summer, cool summer
|
||||
temp_min = season_even(summer, -30.0, 4.0);
|
||||
temp_max = season_even(summer, -20.0, 15.0);
|
||||
_precipitation = season_even(summer, 22.0, 68.0);
|
||||
_precipitation = 50.0 - 25.0*summer;
|
||||
temp_night = season_even(summer, -30.0, 4.0);
|
||||
temp_day = season_even(summer, -20.0, 15.0);
|
||||
precipitation = season_even(summer, 22.0, 68.0);
|
||||
relative_humidity = season_even(summer, 0.70, 0.88);
|
||||
break;
|
||||
case 21: // Dfd: snow, fully humid, extremely continetal
|
||||
temp_min = season_short(summer, -45.0, 4.0);
|
||||
temp_max = season_short(summer, -35.0, 10.0);
|
||||
_precipitation = season_long_low(summer, 7.5, 45.0);
|
||||
temp_night = season_short(summer, -45.0, 4.0);
|
||||
temp_day = season_short(summer, -35.0, 10.0);
|
||||
precipitation = season_long_low(summer, 7.5, 45.0);
|
||||
relative_humidity = season_long_low(summer, 0.80, 0.90);
|
||||
break;
|
||||
case 22: // Dsa: snow, summer dry, hot summer
|
||||
temp_min = season_even(summer, -10.0, 10.0);
|
||||
temp_max = season_even(summer, 0.0, 30.0);
|
||||
_precipitation = season_long_high(summer, 2.0, 70.0);
|
||||
temp_night = season_even(summer, -10.0, 10.0);
|
||||
temp_day = season_even(summer, 0.0, 30.0);
|
||||
precipitation = season_long_high(winter, 2.0, 70.0);
|
||||
relative_humidity = season_long_high(winter, 0.48, 0.58);
|
||||
break;
|
||||
case 23: // Dsb: snow, summer dry, warm summer
|
||||
temp_min = season_even(summer, -15.0, 6.0);
|
||||
temp_max = season_even(summer, -4.0, 25.0);
|
||||
_precipitation = season_long_high(summer, 12.0, 73.0);
|
||||
temp_night = season_even(summer, -15.0, 6.0);
|
||||
temp_day = season_even(summer, -4.0, 25.0);
|
||||
precipitation = season_long_high(winter, 12.0, 73.0);
|
||||
relative_humidity = season_long_high(winter, 0.50, 0.68);
|
||||
break;
|
||||
case 24: // Dsc: snow, summer dry, cool summer
|
||||
temp_min = season_even(summer, -27.5, 2.0);
|
||||
temp_max = season_even(summer, -4.0, 15.0);
|
||||
_precipitation = season_long_low(summer, 32.5, 45.0);
|
||||
temp_night = season_even(summer, -27.5, 2.0);
|
||||
temp_day = season_even(summer, -4.0, 15.0);
|
||||
precipitation = season_long_low(summer, 32.5, 45.0);
|
||||
relative_humidity = season_long_low(summer, 0.50, 0.60);
|
||||
break;
|
||||
case 25: // Dsd: snow, summer dry, extremely continetal
|
||||
temp_min = season_even(summer, -11.5, -6.5);
|
||||
temp_max = season_even(summer, 14.0, 27.0);
|
||||
_precipitation = season_long_low(summer, 5.0, 90.0);
|
||||
temp_night = season_even(summer, -11.5, -6.5);
|
||||
temp_day = season_even(summer, 14.0, 27.0);
|
||||
precipitation = season_long_low(summer, 5.0, 90.0);
|
||||
relative_humidity = season_long_low(summer, 0.48, 0.62);
|
||||
break;
|
||||
case 26: // Dwa: snow, winter dry, hot summer
|
||||
temp_min = season_even(summer, -18.0, 16.5);
|
||||
temp_max = season_even(summer, -5.0, 25.0);
|
||||
_precipitation = season_long_low(summer, 5.0, 180.0);
|
||||
temp_night = season_even(summer, -18.0, 16.5);
|
||||
temp_day = season_even(summer, -5.0, 25.0);
|
||||
precipitation = season_long_low(summer, 5.0, 180.0);
|
||||
relative_humidity = season_long_low(summer, 0.60, 0.68);
|
||||
break;
|
||||
case 27: // Dwb: snow, winter dry, warm summer
|
||||
temp_min = season_even(summer, -28.0, 10.0);
|
||||
temp_max = season_even(summer, -12.5, 22.5);
|
||||
_precipitation = season_long_low(summer, 10.0, 140.0);
|
||||
temp_night = season_even(summer, -28.0, 10.0);
|
||||
temp_day = season_even(summer, -12.5, 22.5);
|
||||
precipitation = season_long_low(summer, 10.0, 140.0);
|
||||
relative_humidity = season_long_low(summer, 0.60, 0.72);
|
||||
break;
|
||||
case 28: // Dwc: snow, winter dry, cool summer
|
||||
temp_min = season_even(summer, -33.0, 5.0);
|
||||
temp_max = season_even(summer, -20.0, 20.0);
|
||||
_precipitation = season_long_low(summer, 10.0, 110.0);
|
||||
temp_night = season_even(summer, -33.0, 5.0);
|
||||
temp_day = season_even(summer, -20.0, 20.0);
|
||||
precipitation = season_long_low(summer, 10.0, 110.0);
|
||||
relative_humidity = season_long_low(summer, 0.60, 0.78);
|
||||
break;
|
||||
case 29: // Dwd: snow, winter dry, extremely continetal
|
||||
temp_min = season_even(summer, -57.5, 0.0);
|
||||
temp_max = season_even(summer, -43.0, 15.0);
|
||||
_precipitation = season_even(summer, 8.0, 63.0);
|
||||
temp_night = season_even(summer, -57.5, 0.0);
|
||||
temp_day = season_even(summer, -43.0, 15.0);
|
||||
precipitation = season_even(summer, 8.0, 63.0);
|
||||
relative_humidity = 0.80;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_temperature_gl = season_even(day, temp_min, temp_max);
|
||||
_temperature_gl = season_even(day, temp_night, temp_day);
|
||||
_temperature_mean = 0.5*(temp_night + temp_day);
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
_temperature_mean = 0.5*(temp_min + temp_max);
|
||||
_precipitation = _precipitation;
|
||||
_relative_humidity = relative_humidity;
|
||||
_precipitation = precipitation;
|
||||
_has_autumn = true;
|
||||
_wind = 3.0;
|
||||
|
||||
double fact_lat = pow(fabs(pos.getLatitudeDeg())/90.0, 2.5);
|
||||
|
@ -446,33 +510,36 @@ void FGClimate::set_polar()
|
|||
double summer = _season_summer;
|
||||
|
||||
// polar climate also occurs high in the mountains
|
||||
double temp_max = _temperature_sl;
|
||||
double temp_min = _temperature_sl;
|
||||
double temp_day = _temperature_sl;
|
||||
double temp_night = _temperature_sl;
|
||||
double precipitation = _precipitation;
|
||||
double relative_humidity = _relative_humidity;
|
||||
switch(_classicfication)
|
||||
{
|
||||
case 30: // EF: polar frost
|
||||
temp_min = season_long_low(summer, -35.0, -6.0);
|
||||
temp_max = season_long_low(summer, -32.5, 0.0);
|
||||
_precipitation = season_even(summer, 50.0, 80.0);
|
||||
temp_night = season_long_low(summer, -35.0, -6.0);
|
||||
temp_day = season_long_low(summer, -32.5, 0.0);
|
||||
precipitation = season_even(summer, 50.0, 80.0);
|
||||
relative_humidity = season_even(summer, 0.65, 0.75);
|
||||
break;
|
||||
case 31: // ET: polar tundra
|
||||
temp_min = season_even(summer, -30.0, 0.0);
|
||||
temp_max = season_even(summer, -22.5, 8.0);
|
||||
_precipitation = season_even(summer, 15.0, 45.0);
|
||||
temp_night = season_even(summer, -30.0, 0.0);
|
||||
temp_day = season_even(summer, -22.5, 8.0);
|
||||
precipitation = season_even(summer, 15.0, 45.0);
|
||||
relative_humidity = season_even(summer, 0.60, 0.88);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_temperature_gl = season_even(day, temp_min, temp_max);
|
||||
_temperature_gl = season_even(day, temp_night, temp_day);
|
||||
_temperature_mean = 0.5*(temp_night + temp_day);
|
||||
_temperature_sl = _temperature_gl;
|
||||
|
||||
_temperature_mean = 0.5*(temp_min + temp_max);
|
||||
_precipitation = _precipitation;
|
||||
_relative_humidity = relative_humidity;
|
||||
_precipitation = precipitation;
|
||||
_has_autumn = false;
|
||||
_wind = 3.0;
|
||||
|
||||
double fact_lat = pow(fabs(pos.getLatitudeDeg())/90.0, 2.5);
|
||||
_relative_humidity = season_even(fact_lat, 0.1, 0.8);
|
||||
}
|
||||
|
||||
void FGClimate::set_environment()
|
||||
|
@ -505,6 +572,7 @@ void FGClimate::set_environment()
|
|||
_snow_thickness = pow(snow_fact, 2.0);
|
||||
_ice_cover = pow(fact_lat, 2.5);
|
||||
|
||||
// less than 20 mm/month of precipitation is considered dry.
|
||||
if (_precipitation < 20.0 && _total_annual_precipitation < 240.0)
|
||||
{
|
||||
_dust_cover = 0.3 - 0.3*sqrtf(_precipitation/20.0);
|
||||
|
@ -514,11 +582,13 @@ void FGClimate::set_environment()
|
|||
else
|
||||
{
|
||||
double wetness = _precipitation - 20.0;
|
||||
wetness = 12.0*wetness/_total_annual_precipitation;
|
||||
wetness = std::min(12.0*wetness/_total_annual_precipitation, 1.0);
|
||||
|
||||
_dust_cover = 0.0;
|
||||
_wetness = pow(wetness, 3.0);
|
||||
|
||||
_lichen_cover = 0.0;
|
||||
_dust_cover = 0.0;
|
||||
double cover = std::min(_total_annual_precipitation, 990.0)/990.0;
|
||||
_lichen_cover = 0.5*pow(wetness*cover, 1.5);
|
||||
}
|
||||
|
||||
if (_environment_adjust)
|
||||
|
@ -529,8 +599,8 @@ void FGClimate::set_environment()
|
|||
fgSetDouble("/environment/surface/dust-cover-factor", _dust_cover);
|
||||
fgSetDouble("/environment/surface/wetness-set", _wetness);
|
||||
fgSetDouble("/environment/surface/lichen-cover-factor", _lichen_cover);
|
||||
if (_autumn)
|
||||
fgSetDouble("/environment/season", 2.0*_season_winter);
|
||||
if (_has_autumn && _is_autumn)
|
||||
fgSetDouble("/environment/season", 2.0*_season_transistional);
|
||||
else
|
||||
fgSetDouble("/environment/season", 0.0);
|
||||
}
|
||||
|
@ -543,6 +613,15 @@ double FGClimate::linear(double val, double min, double max)
|
|||
return min + val*diff;
|
||||
}
|
||||
|
||||
// google: y=1-abs(-1+2*x)
|
||||
// low season is around 0.0 and 1.0, high season around 0.5
|
||||
double FGClimate::triangular(double val, double min, double max)
|
||||
{
|
||||
double diff = max-min;
|
||||
val = 1.0 - fabs(-1.0 + 2*val);
|
||||
return min + val*diff;
|
||||
}
|
||||
|
||||
// google: y =0.5-0.5*atan(cos(x))
|
||||
// the short low season is round 0.0, the short high season around 1.0
|
||||
double FGClimate::season_short(double val, double min, double max)
|
||||
|
@ -569,12 +648,12 @@ double FGClimate::season_long_low(double val, double min, double max)
|
|||
}
|
||||
|
||||
// google: y=0.5+0.5*cos(x^1.5)
|
||||
// 2.145 = pow(SGD_PI, 1.0/1.5)
|
||||
// 2.14503 = pow(SGD_PI, 1.0/1.5)
|
||||
// the long high season is around 0.0, the short low season around 1.0
|
||||
double FGClimate::season_long_high(double val, double min, double max)
|
||||
{
|
||||
double diff = max-min;
|
||||
return min + diff*(0.5 + 0.5*cos(pow(2.145*val, 1.5)));
|
||||
return max + diff*(0.5 + 0.5*cos(pow(2.14503 - 2.14503*val, 1.5)));
|
||||
}
|
||||
|
||||
// goole: y=cos(atan(x*x))
|
||||
|
@ -642,13 +721,13 @@ void FGClimate::report()
|
|||
std::cout << "===============================================" << std::endl;
|
||||
std::cout << "Climate report for:" << std::endl;
|
||||
std::cout << " Date: " << sgTimeFormatTime(t) << " GMT" << std::endl;
|
||||
std::cout << " Sun Latitude: " << _sun_latitude_deg << " deggrees"
|
||||
std::cout << " Sun latitude: " << _sun_latitude_deg << " deg."
|
||||
<< std::endl;
|
||||
std::cout << " Sun Longitude: " << _sun_longitude_deg << " deggrees"
|
||||
std::cout << " Sun longitude: " << _sun_longitude_deg << " deg."
|
||||
<< std::endl;
|
||||
std::cout << " Viewer Latitude: " << pos.getLatitudeDeg() << " deggrees"
|
||||
std::cout << " Viewer latitude: " << pos.getLatitudeDeg() << " deg."
|
||||
<< " (adjusted: " << _adj_latitude_deg << ")" << std::endl;
|
||||
std::cout << " Viewer Longitude: " << pos.getLongitudeDeg() << " deggrees"
|
||||
std::cout << " Viewer longitude: " << pos.getLongitudeDeg() << " deg."
|
||||
<< " (adjusted: " << _adj_longitude_deg << ")" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " Köppen classification: " << koppen_str[_classicfication]
|
||||
|
@ -659,18 +738,22 @@ void FGClimate::report()
|
|||
<< std::endl;
|
||||
std::cout << " Daytime....(0.0 = night .. 1.0 = day): " << _day_noon
|
||||
<< std::endl;
|
||||
std::cout << " Seal level temperature: " << _temperature_sl << " deg. C."
|
||||
std::cout << " Sea level temperature: " << _temperature_sl << " deg. C."
|
||||
<< std::endl;
|
||||
std::cout << " Ground temperature: " << _temperature_gl << " deg. C."
|
||||
std::cout << " Ground temperature: " << _temperature_gl << " deg. C."
|
||||
<< std::endl;
|
||||
std::cout << " Monthly Precipitation: " << _precipitation << " mm"
|
||||
std::cout << " Mean temperature: " << _temperature_mean << " deg. C."
|
||||
<< std::endl;
|
||||
std::cout << " Annual precipitation: " << _total_annual_precipitation
|
||||
std::cout << " Months precipitation: " << _precipitation << " mm"
|
||||
<< std::endl;
|
||||
std::cout << " Annual precipitation: " << _total_annual_precipitation
|
||||
<< " mm" << std::endl;
|
||||
std::cout << " Rel. humidity: "<< _relative_humidity*100.0 << " %"
|
||||
<< std::endl;
|
||||
std::cout << " Dew point: " << _dew_point << " deg. C." << std::endl;
|
||||
std::cout << " Wind: " << _wind << " km/h" << std::endl << std::endl;
|
||||
std::cout << " Snow level: " << _snow_level << " meters" << std::endl;
|
||||
std::cout << " Snow Thickness.(0.0 = thin .. 1.0 = thick): "
|
||||
std::cout << " Snow level: " << _snow_level << " m." << std::endl;
|
||||
std::cout << " Snow thickness.(0.0 = thin .. 1.0 = thick): "
|
||||
<< _snow_thickness << std::endl;
|
||||
std::cout << " Ice cover......(0.0 = none .. 1.0 = thick): " << _ice_cover
|
||||
<< std::endl;
|
||||
|
@ -681,7 +764,8 @@ void FGClimate::report()
|
|||
std::cout << " Lichen cover...(0.0 = none .. 1.0 = mossy): "
|
||||
<< _lichen_cover << std::endl;
|
||||
std::cout << " Season (0.0 = summer .. 1.0 = late autumn): "
|
||||
<< _season_winter << std::endl;
|
||||
<< ((_has_autumn && _is_autumn) ? _season_transistional : 0.0)
|
||||
<< std::endl;
|
||||
std::cout << "===============================================" << std::endl;
|
||||
}
|
||||
#endif // REPORT_TO_CONSOLE
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
// #include <simgear/structure/SGReferenced.hxx>
|
||||
#include <simgear/math/SGGeod.hxx>
|
||||
|
||||
#define REPORT_TO_CONSOLE false
|
||||
#define REPORT_TO_CONSOLE 0
|
||||
|
||||
/*
|
||||
* Update environment parameters based on the Köppen-Geiger climate
|
||||
|
@ -63,6 +63,7 @@ private:
|
|||
#endif
|
||||
// interpolate val (from 0.0 to 1.0) between min and max
|
||||
double linear(double val, double min, double max);
|
||||
double triangular(double val, double min, double max);
|
||||
double season_short(double val, double min, double max);
|
||||
double season_even(double val, double min, double max);
|
||||
double season_long_low(double val, double min, double max);
|
||||
|
@ -98,11 +99,10 @@ private:
|
|||
|
||||
double _day_noon = 1.0;
|
||||
double _season_summer = 1.0;
|
||||
double _season_winter = 0.0;
|
||||
bool _autumn = false;
|
||||
double _season_transistional = 0.0;
|
||||
bool _has_autumn = false;
|
||||
bool _is_autumn = false;
|
||||
|
||||
int _col = 0; // screen coordinates
|
||||
int _row = 0;
|
||||
int _classicfication = 0; // Köppen-Geiger classicfication
|
||||
|
||||
// environment
|
||||
|
|
Loading…
Reference in a new issue