]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.h
Major weather update from Christian Mayer, tying the weather code into
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.h
1 /*****************************************************************************
2
3  Header:       FGLocalWeatherDatabase.h 
4  Author:       Christian Mayer
5  Date started: 28.05.99
6
7  -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
8
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  details.
18
19  You should have received a copy of the GNU General Public License along with
20  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21  Place - Suite 330, Boston, MA  02111-1307, USA.
22
23  Further information about the GNU General Public License can also be found on
24  the world wide web at http://www.gnu.org.
25
26 FUNCTIONAL DESCRIPTION
27 ------------------------------------------------------------------------------
28 Database for the local weather
29 This database is the only one that gets called from FG
30
31 HISTORY
32 ------------------------------------------------------------------------------
33 28.05.1999 Christian Mayer      Created
34 16.06.1999 Durk Talsma          Portability for Linux
35 20.06.1999 Christian Mayer      added lots of consts
36 30.06.1999 Christian Mayer      STL portability
37 11.10.1999 Christian Mayer      changed set<> to map<> on Bernie Bright's 
38                                 suggestion
39 19.10.1999 Christian Mayer      change to use PLIB's sg instead of Point[2/3]D
40                                 and lots of wee code cleaning
41 14.12.1999 Christian Mayer      Changed the internal structure to use Dave
42                                 Eberly's spherical interpolation code. This
43                                 stops our dependancy on the (ugly) voronoi
44                                 code and simplyfies the code structure a lot.
45 18.07.2001 Christian Mayer      Added the posibility to limit the amount of 
46                                 stations for a faster init.
47 *****************************************************************************/
48
49 /****************************************************************************/
50 /* SENTRY                                                                   */
51 /****************************************************************************/
52 #ifndef FGLocalWeatherDatabase_H
53 #define FGLocalWeatherDatabase_H
54
55 /****************************************************************************/
56 /* INCLUDES                                                                 */
57 /****************************************************************************/
58 #include <vector>
59 #include STL_STRING
60
61 #include <plib/sg.h>
62
63 #include <Main/fgfs.hxx>
64
65 #include <simgear/constants.h>
66 #include <simgear/misc/props.hxx>
67
68 #include "sphrintp.h"
69
70 #include "FGPhysicalProperties.h"
71 #include "FGPhysicalProperty.h"
72
73 #include "FGWeatherFeature.h"
74 #include "FGWeatherDefs.h"
75 #include "FGThunderstorm.h"
76
77 /****************************************************************************/
78 /* DEFINES                                                                  */
79 /****************************************************************************/
80 SG_USING_STD(vector);
81 SG_USING_STD(string);
82 SG_USING_NAMESPACE(std);
83
84 /****************************************************************************/
85 /* CLASS DECLARATION                                                        */
86 /****************************************************************************/
87 struct _FGLocalWeatherDatabaseCache
88 {
89     sgVec3             last_known_position;
90     //sgVec3             current_position;
91     SGPropertyNode     *latitude_deg;
92     SGPropertyNode     *longitude_deg;
93     SGPropertyNode     *altitude_ft;
94     FGPhysicalProperty last_known_property;
95 };
96
97 class FGLocalWeatherDatabase : public FGSubsystem
98 {
99 private:
100 protected:
101     SphereInterpolate            *database_logic;
102     vector<FGPhysicalProperties> database_data;
103 #ifndef macintosh
104     FGPhysicalProperties DatabaseEvaluate(const sgVec2& p) const
105     {
106         sgVec2 p_converted = {p[0]*(SGD_2PI/360.0),
107                               p[1]*(SGD_2PI/360.0)};
108         EvaluateData d = database_logic->Evaluate(p_converted);
109         return database_data[d.index[0]]*d.percentage[0] + 
110                database_data[d.index[1]]*d.percentage[1] + 
111                database_data[d.index[2]]*d.percentage[2] ; 
112     }
113 #endif
114     FGPhysicalProperties DatabaseEvaluate(const sgVec3& p) const
115     {
116         sgVec3 p_converted = {p[0]*(SGD_2PI/360.0),
117                               p[1]*(SGD_2PI/360.0),
118                               p[2]                };
119         EvaluateData d = database_logic->Evaluate(p_converted);
120         return database_data[d.index[0]]*d.percentage[0] + 
121                database_data[d.index[1]]*d.percentage[1] + 
122                database_data[d.index[2]]*d.percentage[2] ; 
123     }
124
125     typedef vector<sgVec2>      pointVector;
126     typedef vector<pointVector> tileVector;
127
128     /************************************************************************/
129     /* make tiles out of points on a 2D plane                               */
130     /************************************************************************/
131     WeatherPrecision WeatherVisibility; //how far do I need to simulate the
132                                         //local weather? Unit: metres
133
134     _FGLocalWeatherDatabaseCache *cache;
135     inline void check_cache_for_update(void) const;
136
137     bool Thunderstorm;                  //is there a thunderstorm near by?
138     FGThunderstorm *theThunderstorm;    //pointer to the thunderstorm.
139
140 public:
141     /************************************************************************/
142     /* for tieing them to the property system                               */
143     /************************************************************************/
144     inline WeatherPrecision get_wind_north() const;
145     inline WeatherPrecision get_wind_east() const;
146     inline WeatherPrecision get_wind_up() const;
147     inline WeatherPrecision get_temperature() const;
148     inline WeatherPrecision get_air_pressure() const;
149     inline WeatherPrecision get_vapor_pressure() const;
150     inline WeatherPrecision get_air_density() const;
151
152     static FGLocalWeatherDatabase *theFGLocalWeatherDatabase;  
153     
154     enum DatabaseWorkingType {
155         use_global,     //use global database for data !!obsolete!!
156         use_internet,   //use the weather data that came from the internet
157         manual,         //use only user inputs
158         distant,        //use distant information, e.g. like LAN when used in
159                         //a multiplayer environment
160         random,         //generate weather randomly
161         default_mode    //use only default values
162     };
163
164     DatabaseWorkingType DatabaseStatus;
165
166     void init( const WeatherPrecision visibility,
167                const DatabaseWorkingType type,
168                const string &root );
169
170     /************************************************************************/
171     /* Constructor and Destructor                                           */
172     /************************************************************************/
173     FGLocalWeatherDatabase(
174         const sgVec3&             position,
175         const string&             root,
176         const DatabaseWorkingType type       = PREFERED_WORKING_TYPE,
177         const WeatherPrecision    visibility = DEFAULT_WEATHER_VISIBILITY)
178     {
179         cache = new _FGLocalWeatherDatabaseCache;
180         sgCopyVec3( cache->last_known_position, position );
181
182         init( visibility, type, root );
183
184         theFGLocalWeatherDatabase = this;
185     }
186
187     FGLocalWeatherDatabase(
188         const WeatherPrecision    position_lat,
189         const WeatherPrecision    position_lon,
190         const WeatherPrecision    position_alt,
191         const string&             root,
192         const DatabaseWorkingType type       = PREFERED_WORKING_TYPE,
193         const WeatherPrecision    visibility = DEFAULT_WEATHER_VISIBILITY)
194     {
195         cache = new _FGLocalWeatherDatabaseCache;
196         sgSetVec3( cache->last_known_position, position_lat, position_lon, position_alt );
197
198         init( visibility, type, root );
199
200         theFGLocalWeatherDatabase = this;
201     }
202
203     ~FGLocalWeatherDatabase();
204
205     /************************************************************************/
206     /* reset the whole database                                             */
207     /************************************************************************/
208     void reset(const DatabaseWorkingType type = PREFERED_WORKING_TYPE);
209
210     /************************************************************************/
211     /* update the database. Since the last call we had dt seconds           */
212     /************************************************************************/
213     void update(const WeatherPrecision dt);                     //time has changed
214     void update(const sgVec3& p);                               //position has  changed
215     void update(const sgVec3& p, const WeatherPrecision dt);    //time and/or position has changed
216
217     /************************************************************************/
218     /* define methods requited for FGSubsystem                              */
219     /************************************************************************/
220     virtual void init () { /* do nothing; that's done in the constructor */ };
221     virtual void bind ();
222     virtual void unbind ();
223     virtual void update (int dt) { update((float) dt); };
224
225     /************************************************************************/
226     /* Get the physical properties on the specified point p                 */
227     /************************************************************************/
228 #ifdef macintosh
229     /* fix a problem with mw compilers in that they don't know the
230        difference between the next two methods. Since the first one
231        doesn't seem to be used anywhere, I commented it out. This is
232        supposed to be fixed in the forthcoming CodeWarrior Release
233        6. */
234 #else
235     FGPhysicalProperties get(const sgVec2& p) const;
236 #endif
237     FGPhysicalProperty   get(const sgVec3& p) const;
238
239     WeatherPrecision     getAirDensity(const sgVec3& p) const;
240     
241     /************************************************************************/
242     /* Add a weather feature at the point p and surrounding area            */
243     /************************************************************************/
244     // !! Adds aren't supported anymore !!
245
246     void setSnowRainIntensity   (const WeatherPrecision x, const sgVec2& p);
247     void setSnowRainType        (const SnowRainType x,     const sgVec2& p);
248     void setLightningProbability(const WeatherPrecision x, const sgVec2& p);
249
250     void setProperties(const FGPhysicalProperties2D& x);    //change a property
251
252     /************************************************************************/
253     /* get/set weather visibility                                           */
254     /************************************************************************/
255     void             setWeatherVisibility(const WeatherPrecision visibility);
256     WeatherPrecision getWeatherVisibility(void) const;
257
258     /************************************************************************/
259     /* figure out if there's a thunderstorm that has to be taken care of    */
260     /************************************************************************/
261     void updateThunderstorm(const float dt)
262     {
263         if (Thunderstorm == false)
264             return;
265
266         theThunderstorm->update( dt );
267     }
268 };
269
270 extern FGLocalWeatherDatabase *WeatherDatabase;
271 void fgUpdateWeatherDatabase(void);
272
273 /****************************************************************************/
274 /* get/set weather visibility                                               */
275 /****************************************************************************/
276 void inline FGLocalWeatherDatabase::setWeatherVisibility(const WeatherPrecision visibility)
277 {
278     if (visibility >= MINIMUM_WEATHER_VISIBILITY)
279         WeatherVisibility = visibility;
280     else
281         WeatherVisibility = MINIMUM_WEATHER_VISIBILITY;
282 }
283
284 WeatherPrecision inline FGLocalWeatherDatabase::getWeatherVisibility(void) const
285 {
286     return WeatherVisibility;
287 }
288
289 inline void FGLocalWeatherDatabase::check_cache_for_update(void) const
290 {
291   if ( ( cache->last_known_position[0] == cache->latitude_deg->getFloatValue() ) &&
292        ( cache->last_known_position[1] == cache->longitude_deg->getFloatValue() ) &&
293        ( cache->last_known_position[2] == cache->altitude_ft->getFloatValue() * SG_FEET_TO_METER ) )
294     return; //nothing to do 
295
296   sgVec3 position = { cache->latitude_deg->getFloatValue(), 
297                       cache->longitude_deg->getFloatValue(), 
298                       cache->altitude_ft->getFloatValue() * SG_FEET_TO_METER };
299
300   sgCopyVec3(cache->last_known_position, position);
301   cache->last_known_property = get(position);
302 }
303
304 inline WeatherPrecision FGLocalWeatherDatabase::get_wind_north() const
305 {
306   check_cache_for_update();
307
308   return cache->last_known_property.Wind[0];
309 }
310
311 inline WeatherPrecision FGLocalWeatherDatabase::get_wind_east() const
312 {
313   check_cache_for_update();
314
315   return cache->last_known_property.Wind[1];
316 }
317
318 inline WeatherPrecision FGLocalWeatherDatabase::get_wind_up() const
319 {
320   check_cache_for_update();
321
322   return cache->last_known_property.Wind[2];
323 }
324
325 inline WeatherPrecision FGLocalWeatherDatabase::get_temperature() const
326 {
327   check_cache_for_update();
328
329   return cache->last_known_property.Temperature;
330 }
331
332 inline WeatherPrecision FGLocalWeatherDatabase::get_air_pressure() const
333 {
334   check_cache_for_update();
335
336   return cache->last_known_property.AirPressure;
337 }
338
339 inline WeatherPrecision FGLocalWeatherDatabase::get_vapor_pressure() const
340 {
341   check_cache_for_update();
342
343   return cache->last_known_property.VaporPressure;
344 }
345
346 inline WeatherPrecision FGLocalWeatherDatabase::get_air_density() const
347 {
348   // check_for_update();
349   // not required, as the called functions will do that
350
351   return (get_air_pressure()*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
352          (get_temperature()*FG_WEATHER_DEFAULT_AIRPRESSURE);
353 }
354
355
356 /****************************************************************************/
357 #endif /*FGLocalWeatherDatabase_H*/