Author: Christian Mayer
Date started: 28.05.99
- ---------- Copyright (C) 1999 Christian Mayer (vader@t-online.de) ----------
+ -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
30.06.1999 Christian Mayer STL portability
11.10.1999 Christian Mayer changed set<> to map<> on Bernie Bright's
suggestion
+19.10.1999 Christian Mayer change to use PLIB's sg instead of Point[2/3]D
+ and lots of wee code cleaning
+14.12.1999 Christian Mayer Changed the internal structure to use Dave
+ 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.
*****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/* INCLUDES */
/****************************************************************************/
-//This is only here for smoother code change. In the end the WD should be clean
-//of *any* OpenGL:
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-#include <GL/glut.h>
-#include <XGL/xgl.h>
-
#include <vector>
-#include "sg.h"
+#include STL_STRING
+
+#include <plib/sg.h>
+
+#include <Main/fgfs.hxx>
+
+#include <simgear/constants.h>
+#include <simgear/misc/props.hxx>
+
+#include "sphrintp.h"
#include "FGPhysicalProperties.h"
-#include "FGGlobalWeatherDatabase.h"
-#include "FGMicroWeather.h"
+#include "FGPhysicalProperty.h"
+
#include "FGWeatherFeature.h"
#include "FGWeatherDefs.h"
+#include "FGThunderstorm.h"
/****************************************************************************/
/* DEFINES */
/****************************************************************************/
-FG_USING_STD(vector);
-FG_USING_NAMESPACE(std);
+SG_USING_STD(vector);
+SG_USING_STD(string);
+SG_USING_NAMESPACE(std);
/****************************************************************************/
/* CLASS DECLARATION */
/****************************************************************************/
-class FGLocalWeatherDatabase
+struct _FGLocalWeatherDatabaseCache
+{
+ sgVec3 last_known_position;
+ //sgVec3 current_position;
+ SGPropertyNode *latitude_deg;
+ SGPropertyNode *longitude_deg;
+ SGPropertyNode *altitude_ft;
+ FGPhysicalProperty last_known_property;
+};
+
+class FGLocalWeatherDatabase : public FGSubsystem
{
private:
protected:
- FGGlobalWeatherDatabase *global; //point to the global database
-
- typedef vector<FGMicroWeather> FGMicroWeatherList;
- typedef FGMicroWeatherList::iterator FGMicroWeatherListIt;
-
- typedef vector<Point2D> pointVector;
+ SphereInterpolate *database_logic;
+ vector<FGPhysicalProperties> database_data;
+#ifndef macintosh
+ FGPhysicalProperties DatabaseEvaluate(const sgVec2& p) const
+ {
+ sgVec2 p_converted = {p[0]*(SGD_2PI/360.0),
+ p[1]*(SGD_2PI/360.0)};
+ EvaluateData d = database_logic->Evaluate(p_converted);
+ return database_data[d.index[0]]*d.percentage[0] +
+ database_data[d.index[1]]*d.percentage[1] +
+ database_data[d.index[2]]*d.percentage[2] ;
+ }
+#endif
+ FGPhysicalProperties DatabaseEvaluate(const sgVec3& p) const
+ {
+ sgVec3 p_converted = {p[0]*(SGD_2PI/360.0),
+ p[1]*(SGD_2PI/360.0),
+ p[2] };
+ EvaluateData d = database_logic->Evaluate(p_converted);
+ return database_data[d.index[0]]*d.percentage[0] +
+ database_data[d.index[1]]*d.percentage[1] +
+ database_data[d.index[2]]*d.percentage[2] ;
+ }
+
+ typedef vector<sgVec2> pointVector;
typedef vector<pointVector> tileVector;
/************************************************************************/
/* make tiles out of points on a 2D plane */
/************************************************************************/
- void tileLocalWeather(const FGPhysicalProperties2DVector& EntryList);
+ WeatherPrecision WeatherVisibility; //how far do I need to simulate the
+ //local weather? Unit: metres
- FGMicroWeatherList WeatherAreas;
+ _FGLocalWeatherDatabaseCache *cache;
+ inline void check_cache_for_update(void) const;
- WeatherPrecition WeatherVisibility; //how far do I need to simulate the
- //local weather? Unit: metres
- Point3D last_known_position;
+ 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 {
- use_global, //use global database for data
+ use_global, //use global database for data !!obsolete!!
+ use_internet, //use the weather data that came from the internet
manual, //use only user inputs
distant, //use distant information, e.g. like LAN when used in
//a multiplayer environment
default_mode //use only default values
};
-protected:
DatabaseWorkingType DatabaseStatus;
- /************************************************************************/
- /* return the index of the area with point p */
- /************************************************************************/
- unsigned int AreaWith(const Point2D& p) const;
+ void init( const WeatherPrecision visibility,
+ const DatabaseWorkingType type,
+ const string &root );
-public:
/************************************************************************/
/* Constructor and Destructor */
/************************************************************************/
FGLocalWeatherDatabase(
- const Point3D& posititon,
- const WeatherPrecition& visibility = DEFAULT_WEATHER_VISIBILIY,
- const DatabaseWorkingType& type = PREFERED_WORKING_TYPE);
+ const sgVec3& position,
+ const string& root,
+ const DatabaseWorkingType type = PREFERED_WORKING_TYPE,
+ const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY)
+ {
+ cache = new _FGLocalWeatherDatabaseCache;
+ sgCopyVec3( cache->last_known_position, position );
+
+ init( visibility, type, root );
+
+ theFGLocalWeatherDatabase = this;
+ }
+
+ FGLocalWeatherDatabase(
+ const WeatherPrecision position_lat,
+ const WeatherPrecision position_lon,
+ const WeatherPrecision position_alt,
+ const string& root,
+ const DatabaseWorkingType type = PREFERED_WORKING_TYPE,
+ const WeatherPrecision visibility = DEFAULT_WEATHER_VISIBILITY)
+ {
+ cache = new _FGLocalWeatherDatabaseCache;
+ sgSetVec3( cache->last_known_position, position_lat, position_lon, position_alt );
+
+ init( visibility, type, root );
+
+ theFGLocalWeatherDatabase = this;
+ }
+
~FGLocalWeatherDatabase();
/************************************************************************/
/* reset the whole database */
/************************************************************************/
- void reset(const DatabaseWorkingType& type = PREFERED_WORKING_TYPE);
+ void reset(const DatabaseWorkingType type = PREFERED_WORKING_TYPE);
/************************************************************************/
/* update the database. Since the last call we had dt seconds */
/************************************************************************/
- void update(const WeatherPrecition& dt); //time has changed
- void update(const Point3D& p); //position has changed
- void update(const Point3D& p, const WeatherPrecition& dt); //time and/or position has changed
+ void update(const WeatherPrecision dt); //time has changed
+ void update(const sgVec3& p); //position has changed
+ void update(const sgVec3& p, const WeatherPrecision dt); //time and/or position has changed
+
+ /************************************************************************/
+ /* define methods requited for FGSubsystem */
+ /************************************************************************/
+ virtual void init () { /* do nothing; that's done in the constructor */ };
+ virtual void bind ();
+ virtual void unbind ();
+ virtual void update (int dt) { update((float) dt); };
/************************************************************************/
/* Get the physical properties on the specified point p */
/************************************************************************/
- FGPhysicalProperty get(const Point3D& p) const;
- FGPhysicalProperty get(const sgVec3& p) const;
+#ifdef macintosh
+ /* fix a problem with mw compilers in that they don't know the
+ difference between the next two methods. Since the first one
+ doesn't seem to be used anywhere, I commented it out. This is
+ supposed to be fixed in the forthcoming CodeWarrior Release
+ 6. */
+#else
FGPhysicalProperties get(const sgVec2& p) const;
+#endif
+ FGPhysicalProperty get(const sgVec3& p) const;
- WeatherPrecition getAirDensity(const Point3D& p) const;
- WeatherPrecition getAirDensity(const sgVec3& p) const;
+ WeatherPrecision getAirDensity(const sgVec3& p) const;
/************************************************************************/
/* Add a weather feature at the point p and surrounding area */
/************************************************************************/
+ // !! Adds aren't supported anymore !!
- void addWind(const WeatherPrecition alt, const Point3D& x, const Point2D& p);
- void addTurbulence(const WeatherPrecition alt, const Point3D& x, const Point2D& p);
- void addTemperature(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p);
- void addAirPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p);
- void addVaporPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p);
- void addCloud(const WeatherPrecition alt, const FGCloudItem& x, const Point2D& p);
-
- void setSnowRainIntensity(const WeatherPrecition& x, const Point2D& p);
- void setSnowRainType(const SnowRainType& x, const Point2D& p);
- void setLightningProbability(const WeatherPrecition& x, const Point2D& p);
+ void setSnowRainIntensity (const WeatherPrecision x, const sgVec2& p);
+ void setSnowRainType (const SnowRainType x, const sgVec2& p);
+ void setLightningProbability(const WeatherPrecision x, const sgVec2& p);
- void addProperties(const FGPhysicalProperties2D& x); //add a property
void setProperties(const FGPhysicalProperties2D& x); //change a property
/************************************************************************/
/* get/set weather visibility */
/************************************************************************/
- void setWeatherVisibility(const WeatherPrecition& visibility);
- WeatherPrecition getWeatherVisibility(void) const;
+ void setWeatherVisibility(const WeatherPrecision visibility);
+ WeatherPrecision getWeatherVisibility(void) const;
+
+ /************************************************************************/
+ /* figure out if there's a thunderstorm that has to be taken care of */
+ /************************************************************************/
+ void updateThunderstorm(const float dt)
+ {
+ if (Thunderstorm == false)
+ return;
+
+ theThunderstorm->update( dt );
+ }
};
extern FGLocalWeatherDatabase *WeatherDatabase;
/****************************************************************************/
/* get/set weather visibility */
/****************************************************************************/
-void inline FGLocalWeatherDatabase::setWeatherVisibility(const WeatherPrecition& visibility)
+void inline FGLocalWeatherDatabase::setWeatherVisibility(const WeatherPrecision visibility)
{
- if (visibility >= MINIMUM_WEATHER_VISIBILIY)
+ if (visibility >= MINIMUM_WEATHER_VISIBILITY)
WeatherVisibility = visibility;
else
- WeatherVisibility = MINIMUM_WEATHER_VISIBILIY;
+ WeatherVisibility = MINIMUM_WEATHER_VISIBILITY;
+}
- //This code doesn't belong here as this is the optical visibility and not
- //the visibility of the weather database (that should be bigger...). The
- //optical visibility should be calculated from the vapor pressure e.g.
- //But for the sake of a smoother change from the old way to the new one...
+WeatherPrecision inline FGLocalWeatherDatabase::getWeatherVisibility(void) const
+{
+ return WeatherVisibility;
+}
- GLfloat fog_exp_density;
- GLfloat fog_exp2_density;
-
- // for GL_FOG_EXP
- fog_exp_density = -log(0.01 / WeatherVisibility);
-
- // for GL_FOG_EXP2
- fog_exp2_density = sqrt( -log(0.01) ) / WeatherVisibility;
-
- // Set correct opengl fog density
- xglFogf (GL_FOG_DENSITY, fog_exp2_density);
-
- // FG_LOG( FG_INPUT, FG_DEBUG, "Fog density = " << w->fog_density );
- //cerr << "FGLocalWeatherDatabase::setWeatherVisibility(" << visibility << "):\n";
- //cerr << "Fog density = " << fog_exp_density << "\n";
-
+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);
}
-WeatherPrecition inline FGLocalWeatherDatabase::getWeatherVisibility(void) const
+inline WeatherPrecision FGLocalWeatherDatabase::get_wind_north() const
{
- //cerr << "FGLocalWeatherDatabase::getWeatherVisibility() = " << WeatherVisibility << "\n";
- return WeatherVisibility;
+ 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);
}