1 /*****************************************************************************
3 Module: FGLocalWeatherDatabase.cpp
4 Author: Christian Mayer
6 Called by: main program
8 -------- Copyright (C) 1999 Christian Mayer (fgfs@christianmayer.de) --------
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
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
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.
24 Further information about the GNU General Public License can also be found on
25 the world wide web at http://www.gnu.org.
27 FUNCTIONAL DESCRIPTION
28 ------------------------------------------------------------------------------
29 Database for the local weather
30 This database is the only one that gets called from FG
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
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 *****************************************************************************/
43 /****************************************************************************/
45 /****************************************************************************/
46 #include <Include/compiler.h>
47 #include <Include/fg_constants.h>
49 #include <Aircraft/aircraft.hxx>
51 #include "FGLocalWeatherDatabase.h"
52 #include "FGVoronoi.h"
54 #include "FGWeatherParse.h"
56 /****************************************************************************/
57 /********************************** CODE ************************************/
58 /****************************************************************************/
60 /****************************************************************************/
61 /* return the index (better: ID) of the area with point p */
62 /****************************************************************************/
63 unsigned int FGLocalWeatherDatabase::AreaWith(const sgVec2& p) const
66 for (FGMicroWeatherList::size_type i = 0; i != WeatherAreas.size(); i++)
68 if (WeatherAreas[i].hasPoint(p) == true)
72 return 0; //nothing found
75 /****************************************************************************/
76 /* make tiles out of points on a 2D plane */
77 /****************************************************************************/
78 void FGLocalWeatherDatabase::tileLocalWeather(const FGPhysicalProperties2DVector& EntryList)
80 FGVoronoiInputList input;
82 for (FGPhysicalProperties2DVectorConstIt it1 = EntryList.begin(); it1 != EntryList.end(); it1++)
83 input.push_back(FGVoronoiInput(it1->p, *it1));
85 FGVoronoiOutputList output = Voronoiate(input);
87 for (FGVoronoiOutputList::iterator it2 = output.begin(); it2 != output.end(); it2++)
88 WeatherAreas.push_back(FGMicroWeather(it2->value, it2->boundary));
91 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
92 FGLocalWeatherDatabase *WeatherDatabase;
94 void FGLocalWeatherDatabase::init(const WeatherPrecision visibility, const DatabaseWorkingType type)
96 cerr << "Initializing FGLocalWeatherDatabase\n";
97 cerr << "-----------------------------------\n";
99 if (theFGLocalWeatherDatabase)
101 //FG_LOG( FG_GENERAL, FG_ALERT, "Error: only one local weather allowed" );
102 cerr << "Error: only one local weather allowed";
106 setWeatherVisibility(visibility);
108 DatabaseStatus = type;
109 global = 0; //just get sure...
111 Thunderstorm = false;
112 //I don't need to set theThunderstorm as Thunderstorm == false
114 switch(DatabaseStatus)
118 global = new FGGlobalWeatherDatabase; //initialize GlobalDatabase
119 global->setDatabaseStatus(FGGlobalWeatherDatabase_working);
120 tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
126 FGWeatherParse parsed_data;
128 parsed_data.input( "weather/current.gz" );
129 global = new FGGlobalWeatherDatabase; //initialize GlobalDatabase
130 global->setDatabaseStatus(FGGlobalWeatherDatabase_working);
133 for (unsigned int i = 0; i != parsed_data.stored_stations(); i++)
135 global->add( parsed_data.getFGPhysicalProperties2D(i) );
136 //cerr << parsed_data.getFGPhysicalProperties2D(i);
143 //and finally tile it
144 tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
145 cerr << "Finished weather init.\n";
151 cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
152 cerr << " using random mode instead!\n";
158 vector<sgVec2Wrap> emptyList;
159 WeatherAreas.push_back(FGMicroWeather(FGPhysicalProperties2D(), emptyList)); //in these cases I've only got one tile
164 cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
168 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
172 //delete every stored area
173 WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
175 //delete global database if necessary
176 if (DatabaseStatus == use_global)
180 /****************************************************************************/
181 /* reset the whole database */
182 /****************************************************************************/
183 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType type)
185 //delete global database if necessary
186 if ((DatabaseStatus == use_global) && (type != use_global))
189 DatabaseStatus = type;
190 if (DatabaseStatus == use_global)
191 tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
193 //delete every stored area
194 WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
197 /****************************************************************************/
198 /* update the database. Since the last call we had dt seconds */
199 /****************************************************************************/
200 void FGLocalWeatherDatabase::update(const WeatherPrecision dt)
202 if (DatabaseStatus==use_global)
206 void FGLocalWeatherDatabase::update(const sgVec3& p) //position has changed
208 sgCopyVec3(last_known_position, p);
210 if ( AreaWith(p) == 0 )
211 { //I have moved out of my local area...
213 //now I should erase all my areas and get the new ones
214 //but that takes too long :-( I have to take care about that soon
217 //uncomment this when you are using the GlobalDatabase
219 cerr << "****\nupdate(p) inside\n";
220 cerr << "Parameter: " << p[0] << "/" << p[1] << "/" << p[2] << "\n";
222 sgSetVec2( p2d, p[0], p[1] );
223 cerr << FGPhysicalProperties2D(global->get(p2d), p2d);
228 void FGLocalWeatherDatabase::update(const sgVec3& p, const WeatherPrecision dt) //time and/or position has changed
230 sgCopyVec3(last_known_position, p);
232 if ( AreaWith(p) == 0 )
233 { //I have moved out of my local area...
235 //now I should erase all my areas and get the new ones
236 //but that takes too long :-( I have to take care about that soon
239 if (DatabaseStatus==use_global)
243 /****************************************************************************/
244 /* Get the physical properties on the specified point p out of the database */
245 /****************************************************************************/
246 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
248 unsigned int a = AreaWith(p);
250 return WeatherAreas[a-1].get(p[3]);
251 else //point is outside => ask GlobalWeatherDatabase
252 return global->get(p);
255 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
258 sgSetVec3(temp, p[0], p[1], 0.0);
260 unsigned int a = AreaWith(temp);
262 return WeatherAreas[a-1].get();
263 else //point is outside => ask GlobalWeatherDatabase
264 return global->get(p);
267 WeatherPrecision FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
269 FGPhysicalProperty dummy;
270 unsigned int a = AreaWith(p);
272 dummy = WeatherAreas[a-1].get(p[3]);
273 else //point is outside => ask GlobalWeatherDatabase
274 dummy = global->get(p);
277 (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) /
278 (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
281 /****************************************************************************/
282 /* Add a weather feature at the point p and surrounding area */
283 /****************************************************************************/
284 void FGLocalWeatherDatabase::addWind(const WeatherPrecision alt, const sgVec3& x, const sgVec2& p)
286 unsigned int a = AreaWith(p);
288 WeatherAreas[a-1].addWind(alt, x);
291 void FGLocalWeatherDatabase::addTurbulence(const WeatherPrecision alt, const sgVec3& x, const sgVec2& p)
293 unsigned int a = AreaWith(p);
295 WeatherAreas[a-1].addTurbulence(alt, x);
298 void FGLocalWeatherDatabase::addTemperature(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
300 unsigned int a = AreaWith(p);
302 WeatherAreas[a-1].addTemperature(alt, x);
305 void FGLocalWeatherDatabase::addAirPressure(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
307 unsigned int a = AreaWith(p);
309 WeatherAreas[a-1].addAirPressure(alt, x);
312 void FGLocalWeatherDatabase::addVaporPressure(const WeatherPrecision alt, const WeatherPrecision x, const sgVec2& p)
314 unsigned int a = AreaWith(p);
316 WeatherAreas[a-1].addVaporPressure(alt, x);
319 void FGLocalWeatherDatabase::addCloud(const WeatherPrecision alt, const FGCloudItem& x, const sgVec2& p)
321 unsigned int a = AreaWith(p);
323 WeatherAreas[a-1].addCloud(alt, x);
326 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecision x, const sgVec2& p)
328 unsigned int a = AreaWith(p);
330 WeatherAreas[a-1].setSnowRainIntensity(x);
333 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType x, const sgVec2& p)
335 unsigned int a = AreaWith(p);
337 WeatherAreas[a-1].setSnowRainType(x);
340 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecision x, const sgVec2& p)
342 unsigned int a = AreaWith(p);
344 WeatherAreas[a-1].setLightningProbability(x);
347 void FGLocalWeatherDatabase::addProperties(const FGPhysicalProperties2D& x)
349 if (DatabaseStatus==use_global)
353 //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
354 //changes my voronoi diagram but I don't update it! instead I'm changing one local value
355 //that could be anywhere!!
356 //This only *might* work when the plane moves so far so fast that the diagram gets newly
358 unsigned int a = AreaWith(x.p);
360 WeatherAreas[a-1].setStoredWeather(x);
364 unsigned int a = AreaWith(x.p);
366 WeatherAreas[a-1].setStoredWeather(x);
370 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
372 if (DatabaseStatus==use_global)
376 //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
377 //changes my voronoi diagram but I don't update it! Instead I'm changing one local value
378 //that could be anywhere!!
379 //This only *might* work when the plane moves so far so fast that the diagram gets newly
381 unsigned int a = AreaWith(x.p);
383 WeatherAreas[a-1].setStoredWeather(x);
387 unsigned int a = AreaWith(x.p);
389 WeatherAreas[a-1].setStoredWeather(x);
393 void fgUpdateWeatherDatabase(void)
395 //cerr << "FGLocalWeatherDatabase::update()\n";
398 current_aircraft.fdm_state->get_Latitude(),
399 current_aircraft.fdm_state->get_Longitude(),
400 current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER);
402 WeatherDatabase->update( position );