sgSetVec3( position, current_aircraft.fdm_state->get_Latitude(),
current_aircraft.fdm_state->get_Longitude(),
current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER );
- FGLocalWeatherDatabase::theFGLocalWeatherDatabase =
+ double init_vis = fgGetDouble("/environment/visibility-m");
+
+ FGLocalWeatherDatabase::DatabaseWorkingType working_type;
+
+ if (fgGetString("/environment/weather/working-type") == "internet")
+ {
+ working_type = FGLocalWeatherDatabase::use_internet;
+ } else {
+ working_type = FGLocalWeatherDatabase::default_mode;
+ }
+
+ if ( init_vis > 0 ) {
+ FGLocalWeatherDatabase::theFGLocalWeatherDatabase =
new FGLocalWeatherDatabase( position,
- globals->get_fg_root() );
+ globals->get_fg_root(),
+ working_type,
+ init_vis );
+ } else {
+ FGLocalWeatherDatabase::theFGLocalWeatherDatabase =
+ new FGLocalWeatherDatabase( position,
+ globals->get_fg_root(),
+ working_type );
+ }
+
// cout << theFGLocalWeatherDatabase << endl;
// cout << "visibility = "
// << theFGLocalWeatherDatabase->getWeatherVisibility() << endl;
WeatherDatabase = FGLocalWeatherDatabase::theFGLocalWeatherDatabase;
-
- double init_vis = fgGetDouble("/environment/visibility-m");
- if ( init_vis > 0 ) {
- WeatherDatabase->setWeatherVisibility( init_vis );
- }
// register the periodic update of the weather
global_events.Register( "weather update", fgUpdateWeatherDatabase,
on 'the bus'
18.05.2000 Christian Mayer Minor clean-ups. Changed the code to use
FGWeatherUtils.h for unit conversion
+18.07.2001 Christian Mayer Added the posibility to limit the amount of
+ stations for a faster init.
*****************************************************************************/
/****************************************************************************/
#include <simgear/constants.h>
#include <Aircraft/aircraft.hxx>
+#include <Main/fg_props.hxx>
#include "FGLocalWeatherDatabase.h"
case use_internet:
{
FGWeatherParse *parsed_data = new FGWeatherParse();
-
- parsed_data->input( "weather/current.gz" );
+ sgVec2 *p;
+ FGPhysicalProperties *f;
+ string path_to_weather = root + "/weather/current.txt.gz";
+ parsed_data->input( path_to_weather.c_str() );
unsigned int n = parsed_data->stored_stations();
-
- sgVec2 *p = new sgVec2 [n];
- FGPhysicalProperties *f = new FGPhysicalProperties[n];
-
- // fill the database
- for (unsigned int i = 0; i < n; i++)
- {
- f[i] = parsed_data->getFGPhysicalProperties(i);
- parsed_data->getPosition(i, p[i]);
-
- if ( (i%100) == 0)
- cerr << ".";
- }
+ int m = fgGetInt("/environment/weather/max-stations", -1);
+
+ if ( ( m < 0 ) || ( m > n ) )
+ {
+ m = n;
+
+ p = new sgVec2 [n];
+ f = new FGPhysicalProperties[n];
+
+ // fill the database
+ for (unsigned int i = 0; i < n; i++)
+ {
+ f[i] = parsed_data->getFGPhysicalProperties(i);
+ parsed_data->getPosition(i, p[i]);
+
+ if ( (i%100) == 0)
+ cerr << ".";
+ }
+ }
+ else
+ { // we have to limit the amount of stations
+
+ //store the "distance" between the station and the current
+ //position. As the distance is calculated from the lat/lon
+ //values it's not worth much - but it's good enough for
+ //comparison
+ map<float, unsigned int> squared_distance;
+ sgVec2 cur_pos;
+
+ cur_pos[0] = cache->last_known_position[0];
+ cur_pos[1] = cache->last_known_position[1];
+
+ unsigned int i;
+ for( i = 0; i < n; i++ )
+ {
+ sgVec2 pos;
+ parsed_data->getPosition(i, pos);
+ squared_distance[sgDistanceSquaredVec2(cur_pos, pos)] = i;
+ }
+
+ p = new sgVec2 [m];
+ f = new FGPhysicalProperties[m];
+
+ map<float, unsigned int>::const_iterator ci;
+ ci = squared_distance.begin();
+
+ // fill the database
+ for ( i = 0; i < m; i++ )
+ {
+ f[i] = parsed_data->getFGPhysicalProperties(ci->second);
+ parsed_data->getPosition(ci->second, p[i]);
+
+ if ( (i%100) == 0)
+ cerr << ".";
+
+ ci++;
+ }
+ }
// free the memory of the parsed data to ease the required memory
// for the very memory consuming spherical interpolation
delete parsed_data;
//and finally init the interpolation
- cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350)\n";
- database = new SphereInterpolate<FGPhysicalProperties>(n, p, f);
+ cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350 for ca. 3500 stations)\n";
+ database = new SphereInterpolate<FGPhysicalProperties>(m, p, f);
//and free my allocations:
delete[] p;
default:
cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
};
+
+ cache->latitude_deg = fgGetNode("/position/latitude-deg" );
+ cache->longitude_deg = fgGetNode("/position/longitude-deg");
+ cache->altitude_ft = fgGetNode("/position/altitude-ft" );
+
+ fgTie("/environment/weather/wind-north-mps", this, &FGLocalWeatherDatabase::get_wind_north);
+ fgTie("/environment/weather/wind-east-mps", this, &FGLocalWeatherDatabase::get_wind_east);
+ fgTie("/environment/weather/wind-up-mps", this, &FGLocalWeatherDatabase::get_wind_up);
+ fgTie("/environment/weather/temperature-K", this, &FGLocalWeatherDatabase::get_temperature);
+ fgTie("/environment/weather/air-pressure-Pa", this, &FGLocalWeatherDatabase::get_air_pressure);
+ fgTie("/environment/weather/vapor-pressure-Pa", this, &FGLocalWeatherDatabase::get_vapor_pressure);
+ fgTie("/environment/weather/air-density", this, &FGLocalWeatherDatabase::get_air_density);
}
FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
{
- sgCopyVec3(last_known_position, p);
-
//uncomment this when you are using the GlobalDatabase
/*
cerr << "****\nupdate(p) inside\n";
cerr << "Parameter: " << p[0] << "/" << p[1] << "/" << p[2] << "\n";
- sgVec2 p2d;
- sgSetVec2( p2d, p[0], p[1] );
cerr << FGPhysicalProperties2D(get(p2d), p2d);
cerr << "****\n";
*/
void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt) //time and/or position has changed
{
- sgCopyVec3(last_known_position, p);
}
/****************************************************************************/
void fgUpdateWeatherDatabase(void)
{
sgVec3 position;
- sgVec3 wind;
-
sgSetVec3(position,
current_aircraft.fdm_state->get_Latitude(),
Eberly's spherical interpolation code. This
stops our dependancy on the (ugly) voronoi
code and simplyfies the code structure a lot.
+18.07.2001 Christian Mayer Added the posibility to limit the amount of
+ stations for a faster init.
*****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/* CLASS DECLARATION */
/****************************************************************************/
+struct _FGLocalWeatherDatabaseCache
+{
+ sgVec3 last_known_position;
+ //sgVec3 current_position;
+ SGPropertyNode *latitude_deg;
+ SGPropertyNode *longitude_deg;
+ SGPropertyNode *altitude_ft;
+ FGPhysicalProperty last_known_property;
+};
+
class FGLocalWeatherDatabase
{
private:
/************************************************************************/
WeatherPrecision WeatherVisibility; //how far do I need to simulate the
//local weather? Unit: metres
- sgVec3 last_known_position;
+
+ _FGLocalWeatherDatabaseCache *cache;
+ inline void check_cache_for_update(void) const;
bool Thunderstorm; //is there a thunderstorm near by?
FGThunderstorm *theThunderstorm; //pointer to the thunderstorm.
public:
+ /************************************************************************/
+ /* for tieing them to the property system */
+ /************************************************************************/
+ inline WeatherPrecision get_wind_north() const;
+ inline WeatherPrecision get_wind_east() const;
+ inline WeatherPrecision get_wind_up() const;
+ inline WeatherPrecision get_temperature() const;
+ inline WeatherPrecision get_air_pressure() const;
+ inline WeatherPrecision get_vapor_pressure() const;
+ inline WeatherPrecision get_air_density() const;
+
static FGLocalWeatherDatabase *theFGLocalWeatherDatabase;
enum DatabaseWorkingType {
FGLocalWeatherDatabase(
const sgVec3& position,
const string& root,
- const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY,
- const DatabaseWorkingType type = PREFERED_WORKING_TYPE)
+ const DatabaseWorkingType type = PREFERED_WORKING_TYPE,
+ const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY)
{
- sgCopyVec3( last_known_position, position );
+ cache = new _FGLocalWeatherDatabaseCache;
+ sgCopyVec3( cache->last_known_position, position );
init( visibility, type, root );
const WeatherPrecision position_lon,
const WeatherPrecision position_alt,
const string& root,
- const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY,
- const DatabaseWorkingType type = PREFERED_WORKING_TYPE)
+ const DatabaseWorkingType type = PREFERED_WORKING_TYPE,
+ const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY)
{
- sgSetVec3( last_known_position, position_lat, position_lon, position_alt );
+ cache = new _FGLocalWeatherDatabaseCache;
+ sgSetVec3( cache->last_known_position, position_lat, position_lon, position_alt );
init( visibility, type, root );
return WeatherVisibility;
}
+inline void FGLocalWeatherDatabase::check_cache_for_update(void) const
+{
+ if ( ( cache->last_known_position[0] == cache->latitude_deg->getFloatValue() ) &&
+ ( cache->last_known_position[1] == cache->longitude_deg->getFloatValue() ) &&
+ ( cache->last_known_position[2] == cache->altitude_ft->getFloatValue() * SG_FEET_TO_METER ) )
+ return; //nothing to do
+
+ sgVec3 position = { cache->latitude_deg->getFloatValue(),
+ cache->longitude_deg->getFloatValue(),
+ cache->altitude_ft->getFloatValue() * SG_FEET_TO_METER };
+
+ sgCopyVec3(cache->last_known_position, position);
+ cache->last_known_property = get(position);
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_wind_north() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.Wind[0];
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_wind_east() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.Wind[1];
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_wind_up() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.Wind[2];
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_temperature() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.Temperature;
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_air_pressure() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.AirPressure;
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_vapor_pressure() const
+{
+ check_cache_for_update();
+
+ return cache->last_known_property.VaporPressure;
+}
+
+inline WeatherPrecision FGLocalWeatherDatabase::get_air_density() const
+{
+ // check_for_update();
+ // not required, as the called functions will do that
+
+ return (get_air_pressure()*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) /
+ (get_temperature()*FG_WEATHER_DEFAULT_AIRPRESSURE);
+}
+
/****************************************************************************/
#endif /*FGLocalWeatherDatabase_H*/