]> git.mxchange.org Git - flightgear.git/blobdiff - src/WeatherCM/FGLocalWeatherDatabase.h
Erik Hofman:
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.h
index 5be5482572c7e42a203fdbe4f1ae7e6ea4893e7f..60063fa173bbdc7ae5fe9a04a42f9204e01f44f2 100644 (file)
@@ -4,7 +4,7 @@
  Author:       Christian Mayer
  Date started: 28.05.99
 
  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
 
  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
@@ -34,6 +34,16 @@ HISTORY
 16.06.1999 Durk Talsma         Portability for Linux
 20.06.1999 Christian Mayer     added lots of consts
 30.06.1999 Christian Mayer     STL portability
 16.06.1999 Durk Talsma         Portability for Linux
 20.06.1999 Christian Mayer     added lots of consts
 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.
 *****************************************************************************/
 
 /****************************************************************************/
 *****************************************************************************/
 
 /****************************************************************************/
@@ -45,60 +55,105 @@ HISTORY
 /****************************************************************************/
 /* INCLUDES                                                                */
 /****************************************************************************/
 /****************************************************************************/
 /* 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 <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 "FGPhysicalProperties.h"
-#include "FGGlobalWeatherDatabase.h"
-#include "FGMicroWeather.h"
+#include "FGPhysicalProperty.h"
+
 #include "FGWeatherFeature.h"
 #include "FGWeatherDefs.h"
 #include "FGWeatherFeature.h"
 #include "FGWeatherDefs.h"
+#include "FGThunderstorm.h"
 
 /****************************************************************************/
 /* DEFINES                                                                 */
 /****************************************************************************/
 
 /****************************************************************************/
 /* DEFINES                                                                 */
 /****************************************************************************/
-FG_USING_STD(vector);
-FG_USING_NAMESPACE(std);
+SG_USING_STD(vector);
+SG_USING_STD(string);
+SG_USING_NAMESPACE(std);
 
 /****************************************************************************/
 /* CLASS DECLARATION                                                       */
 /****************************************************************************/
 
 /****************************************************************************/
 /* 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:
 {
 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                              */
     /************************************************************************/
     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:
 
 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 {
     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
        manual,         //use only user inputs
        distant,        //use distant information, e.g. like LAN when used in
                        //a multiplayer environment
@@ -106,68 +161,110 @@ public:
        default_mode    //use only default values
     };
 
        default_mode    //use only default values
     };
 
-protected:
     DatabaseWorkingType DatabaseStatus;
 
     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(
     /************************************************************************/
     /* 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                                                    */
     /************************************************************************/
     ~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          */
     /************************************************************************/
 
     /************************************************************************/
     /* 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                */
     /************************************************************************/
 
     /************************************************************************/
     /* 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           */
     /************************************************************************/
     
     /************************************************************************/
     /* Add a weather feature at the point p and surrounding area           */
     /************************************************************************/
+    // !! Adds aren't supported anymore !!
 
 
-    void addWind(const FGWindItem& x, const Point2D& p);
-    void addTurbulence(const FGTurbulenceItem& x, const Point2D& p);
-    void addTemperature(const FGTemperatureItem& x, const Point2D& p);
-    void addAirPressure(const FGAirPressureItem& x, const Point2D& p);
-    void addVaporPressure(const FGVaporPressureItem& x, const Point2D& p);
-    void addCloud(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 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;
 };
 
 extern FGLocalWeatherDatabase *WeatherDatabase;
@@ -176,41 +273,83 @@ void fgUpdateWeatherDatabase(void);
 /****************************************************************************/
 /* get/set weather visibility                                              */
 /****************************************************************************/
 /****************************************************************************/
 /* 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 = 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);
 }
 
 
 }