]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.cpp
262414451d3f80d581e0dd51cbbea35d16199291
[flightgear.git] / src / WeatherCM / FGLocalWeatherDatabase.cpp
1 /*****************************************************************************
2
3  Module:       FGLocalWeatherDatabase.cpp
4  Author:       Christian Mayer
5  Date started: 28.05.99
6  Called by:    main program
7
8  -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 Database for the local weather
30 This database is the only one that gets called from FG
31
32 HISTORY
33 ------------------------------------------------------------------------------
34 28.05.1999 Christian Mayer      Created
35 16.06.1999 Durk Talsma          Portability for Linux
36 20.06.1999 Christian Mayer      added lots of consts
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 07.05.2000 Tony Peden           Added functionality to get the weather data
46                                 on 'the bus'
47 18.05.2000 Christian Mayer      Minor clean-ups. Changed the code to use 
48                                 FGWeatherUtils.h for unit conversion
49 18.07.2001 Christian Mayer      Added the posibility to limit the amount of 
50                                 stations for a faster init.
51 *****************************************************************************/
52
53 /****************************************************************************/
54 /* INCLUDES                                                                 */
55 /****************************************************************************/
56 #include <simgear/compiler.h>
57 #include <simgear/constants.h>
58
59 #include <Aircraft/aircraft.hxx>
60 #include <Main/fg_props.hxx>
61
62 #include "FGLocalWeatherDatabase.h"
63
64 #include "FGWeatherParse.h"
65
66 #include "FGWeatherUtils.h"
67
68 /****************************************************************************/
69 /********************************** CODE ************************************/
70 /****************************************************************************/
71
72 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
73 FGLocalWeatherDatabase *WeatherDatabase;
74
75 void FGLocalWeatherDatabase::init( const WeatherPrecision visibility,
76                                    const DatabaseWorkingType type,
77                                    const string &root )
78 {
79     FGPhysicalProperties f[2];  //make an standard weather that's the same at the whole world
80
81     cerr << "Initializing FGLocalWeatherDatabase\n";
82     cerr << "-----------------------------------\n";
83
84     if (theFGLocalWeatherDatabase)
85     {
86         cerr << "Error: only one local weather allowed";
87         exit(-1);
88     }
89
90     setWeatherVisibility(visibility);
91
92     DatabaseStatus = type;
93     database = 0;           //just get sure...
94
95     Thunderstorm = false;
96     //I don't need to set theThunderstorm as Thunderstorm == false
97
98     switch(DatabaseStatus)
99     {
100     case use_global:
101         {
102             cerr << "Error: there's no global database anymore!\n";
103             exit(-1);
104         }
105         break;
106
107     case use_internet:
108         {
109             FGWeatherParse *parsed_data = new FGWeatherParse();
110             sgVec2               *p;
111             FGPhysicalProperties *f;
112             string path_to_weather = root + "/weather/current.txt.gz";
113             parsed_data->input( path_to_weather.c_str() );
114             unsigned int n = parsed_data->stored_stations();
115             int m = fgGetInt("/environment/weather/max-stations", -1);
116
117             if ( ( m < 0 ) || ( m > n ) )
118             {
119                 m = n;
120
121                 p = new sgVec2              [n];
122                 f = new FGPhysicalProperties[n];
123
124                 // fill the database
125                 for (unsigned int i = 0; i < n; i++) 
126                 {
127                     f[i] = parsed_data->getFGPhysicalProperties(i);
128                     parsed_data->getPosition(i, p[i]);
129
130                     if ( (i%100) == 0)
131                         cerr << ".";
132                 }
133             }
134             else
135             {   // we have to limit the amount of stations
136
137                 //store the "distance" between the station and the current
138                 //position. As the distance is calculated from the lat/lon
139                 //values it's not worth much - but it's good enough for
140                 //comparison
141                 map<float, unsigned int> squared_distance;
142                 sgVec2 cur_pos;
143
144                 cur_pos[0] = cache->last_known_position[0];
145                 cur_pos[1] = cache->last_known_position[1];
146                 
147                 unsigned int i;
148                 for( i = 0; i < n; i++ )
149                 {
150                   sgVec2 pos;
151                   parsed_data->getPosition(i, pos);
152                   squared_distance[sgDistanceSquaredVec2(cur_pos, pos)] = i;
153                 }
154
155                 p = new sgVec2              [m];
156                 f = new FGPhysicalProperties[m];
157
158                 map<float, unsigned int>::const_iterator ci;
159                 ci = squared_distance.begin();
160
161                 // fill the database
162                 for ( i = 0; i < m; i++ ) 
163                 { 
164                     f[i] = parsed_data->getFGPhysicalProperties(ci->second);
165                     parsed_data->getPosition(ci->second, p[i]);
166
167                     if ( (i%100) == 0)
168                         cerr << ".";
169
170                     ci++;
171                 }
172             }
173
174             // free the memory of the parsed data to ease the required memory
175             // for the very memory consuming spherical interpolation
176             delete parsed_data;
177
178             //and finally init the interpolation
179             cerr << "\nInitialiating Interpolation. (2-3 minutes on a PII-350 for ca. 3500 stations)\n";
180             database = new SphereInterpolate<FGPhysicalProperties>(m, p, f);
181
182             //and free my allocations:
183             delete[] p;
184             delete[] f;
185             cerr << "Finished weather init.\n";
186
187         }
188         break;
189
190     case distant:
191         cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
192         cerr << "  using random mode instead!\n";
193     case random:
194     case manual:
195     case default_mode:
196         {
197             double x[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
198             double y[2] = {0.0,  0.0};  //make an standard weather that's the same at the whole world
199             double z[2] = {1.0, -1.0};  //make an standard weather that's the same at the whole world
200             database = new SphereInterpolate<FGPhysicalProperties>(2,x,y,z,f);
201         }
202         break;
203
204     default:
205         cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
206     };
207
208     cache->latitude_deg  = fgGetNode("/position/latitude-deg" );
209     cache->longitude_deg = fgGetNode("/position/longitude-deg");
210     cache->altitude_ft   = fgGetNode("/position/altitude-ft"  );
211
212     fgTie("/environment/weather/wind-north-mps", this, &FGLocalWeatherDatabase::get_wind_north);
213     fgTie("/environment/weather/wind-east-mps", this, &FGLocalWeatherDatabase::get_wind_east);
214     fgTie("/environment/weather/wind-up-mps", this, &FGLocalWeatherDatabase::get_wind_up);
215     fgTie("/environment/weather/temperature-K", this, &FGLocalWeatherDatabase::get_temperature);
216     fgTie("/environment/weather/air-pressure-Pa", this, &FGLocalWeatherDatabase::get_air_pressure);
217     fgTie("/environment/weather/vapor-pressure-Pa", this, &FGLocalWeatherDatabase::get_vapor_pressure);
218     fgTie("/environment/weather/air-density", this, &FGLocalWeatherDatabase::get_air_density);
219 }
220
221 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
222 {
223     //Tidying up:
224     delete database;
225 }
226
227 /****************************************************************************/
228 /* reset the whole database                                                 */
229 /****************************************************************************/
230 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType type)
231 {
232     cerr << "FGLocalWeatherDatabase::reset isn't supported yet\n";
233 }
234
235 /****************************************************************************/
236 /* update the database. Since the last call we had dt seconds               */
237 /****************************************************************************/
238 void FGLocalWeatherDatabase::update(const WeatherPrecision dt)
239 {
240     //if (DatabaseStatus==use_global)
241     //  global->update(dt);
242 }
243
244 void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
245 {
246     //uncomment this when you are using the GlobalDatabase
247     /*
248     cerr << "****\nupdate(p) inside\n";
249     cerr << "Parameter: " << p[0] << "/" << p[1] << "/" << p[2] << "\n";
250     cerr << FGPhysicalProperties2D(get(p2d), p2d);
251     cerr << "****\n";
252     */
253     
254 }
255
256 void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt)   //time and/or position has changed
257 {
258 }
259
260 /****************************************************************************/
261 /* Get the physical properties on the specified point p out of the database */
262 /****************************************************************************/
263 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
264 {
265     return FGPhysicalProperty(database->Evaluate(p), p[2]);
266 }
267
268 #ifdef macintosh
269     /* fix a problem with mw compilers in that they don't know the
270        difference between the next two methods. Since the first one
271        doesn't seem to be used anywhere, I commented it out. This is
272        supposed to be fixed in the forthcoming CodeWarrior Release
273        6. */
274 #else
275 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
276 {
277     return database->Evaluate(p);
278 }
279 #endif
280
281 WeatherPrecision FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
282 {
283     FGPhysicalProperty dummy(database->Evaluate(p), p[2]);
284
285     return 
286         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
287         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
288 }
289
290
291 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecision x, const sgVec2& p)
292 {
293     /* not supported yet */
294 }
295
296 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType x, const sgVec2& p)
297 {
298     /* not supported yet */
299 }
300
301 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecision x, const sgVec2& p)
302 {
303     /* not supported yet */
304 }
305
306 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
307 {
308     /* not supported yet */
309 }
310
311 void fgUpdateWeatherDatabase(void)
312 {
313     sgVec3 position;
314     
315     sgSetVec3(position, 
316         current_aircraft.fdm_state->get_Latitude(),
317         current_aircraft.fdm_state->get_Longitude(),
318         current_aircraft.fdm_state->get_Altitude() * SG_FEET_TO_METER);
319     
320     WeatherDatabase->update( position );
321        
322     // get the data on 'the bus' for the FDM
323
324    /*  FGPhysicalProperty porperty = WeatherDatabase->get(position);
325
326     current_aircraft.fdm_state->set_Static_temperature( Kelvin2Rankine(porperty.Temperature) );
327     current_aircraft.fdm_state->set_Static_pressure( Pascal2psf(porperty.AirPressure) );
328
329     current_aircraft.fdm_state->set_Density( SIdensity2JSBsim( Density(porperty.AirPressure, porperty.Temperature) ) );
330     
331 #define MSTOFPS  3.2808 //m/s to ft/s
332     current_aircraft.fdm_state->set_Velocities_Local_Airmass(porperty.Wind[1]*MSTOFPS,
333         porperty.Wind[0]*MSTOFPS,
334         porperty.Wind[2]*MSTOFPS); */
335
336     
337 }
338