1 /*****************************************************************************
3 Module: FGLocalWeatherDatabase.cpp
4 Author: Christian Mayer
6 Called by: main program
8 ---------- Copyright (C) 1999 Christian Mayer (vader@t-online.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 *****************************************************************************/
41 /****************************************************************************/
43 /****************************************************************************/
44 #include "FGLocalWeatherDatabase.h"
45 #include "FGVoronoi.h"
46 #include "fg_constants.h"
48 #include <Aircraft/aircraft.hxx>
49 #include <Include/fg_constants.h>
51 /****************************************************************************/
52 /********************************** CODE ************************************/
53 /****************************************************************************/
55 /****************************************************************************/
56 /* return the index (better: ID) of the area with point p */
57 /****************************************************************************/
58 unsigned int FGLocalWeatherDatabase::AreaWith(const Point2D& p) const
61 for (FGMicroWeatherList::size_type i = 0; i != WeatherAreas.size(); i++)
63 if (WeatherAreas[i].hasPoint(p) == true)
67 return 0; //nothing found
70 /****************************************************************************/
71 /* make tiles out of points on a 2D plane */
72 /****************************************************************************/
73 void FGLocalWeatherDatabase::tileLocalWeather(const FGPhysicalProperties2DVector& EntryList)
75 FGVoronoiInputList input;
77 for (FGPhysicalProperties2DVector::const_iterator it1 = EntryList.begin(); it1 != EntryList.end(); it1++)
78 input.push_back(FGVoronoiInput(it1->p, *it1));
80 FGVoronoiOutputList output = Voronoiate(input);
82 for (FGVoronoiOutputList::iterator it2 = output.begin(); it2 != output.end(); it2++)
83 WeatherAreas.push_back(FGMicroWeather(it2->value, it2->boundary));
86 /****************************************************************************/
87 /* Constructor and Destructor */
88 /****************************************************************************/
89 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
90 FGLocalWeatherDatabase *WeatherDatabase;
92 FGLocalWeatherDatabase::FGLocalWeatherDatabase(const Point3D& posititon, const WeatherPrecition& visibility, const DatabaseWorkingType& type)
94 cerr << "Initializing FGLocalWeatherDatabase\n";
95 cerr << "-----------------------------------\n";
97 if (theFGLocalWeatherDatabase)
99 //FG_LOG( FG_GENERAL, FG_ALERT, "Error: only one local weather allowed" );
100 cerr << "Error: only one local weather allowed";
104 setWeatherVisibility(visibility);
105 //WeatherVisibility = visibility;
106 DatabaseStatus = type;
107 global = 0; //just get sure...
108 last_known_position = posititon;
111 theFGLocalWeatherDatabase = this;
113 switch(DatabaseStatus)
117 global = new FGGlobalWeatherDatabase; //initialize GlobalDatabase
118 global->setDatabaseStatus(FGGlobalWeatherDatabase_working);
119 tileLocalWeather(global->getAll(posititon, WeatherVisibility, 3));
124 cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
125 cerr << " using random mode instead!\n";
130 vector<Point2D> emptyList;
131 WeatherAreas.push_back(FGMicroWeather(FGPhysicalProperties2D(), emptyList)); //in these cases I've only got one tile
136 cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
140 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
144 //delete every stored area
145 WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
147 //delete global database if necessary
148 if (DatabaseStatus == use_global)
152 /****************************************************************************/
153 /* reset the whole database */
154 /****************************************************************************/
155 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType& type)
157 //delete global database if necessary
158 if ((DatabaseStatus == use_global) && (type != use_global))
161 DatabaseStatus = type;
162 if (DatabaseStatus == use_global)
163 tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
165 //delete every stored area
166 WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
169 /****************************************************************************/
170 /* update the database. Since the last call we had dt seconds */
171 /****************************************************************************/
172 void FGLocalWeatherDatabase::update(const WeatherPrecition& dt)
174 if (DatabaseStatus==use_global)
178 void FGLocalWeatherDatabase::update(const Point3D& p) //position has changed
180 last_known_position = p;
181 //cerr << "****\nupdate inside\n";
182 //cerr << "Parameter: " << p << "\n";
186 void FGLocalWeatherDatabase::update(const Point3D& p, const WeatherPrecition& dt) //time and/or position has changed
188 last_known_position = p;
190 if (DatabaseStatus==use_global)
194 /****************************************************************************/
195 /* Get the physical properties on the specified point p out of the database */
196 /****************************************************************************/
197 FGPhysicalProperty FGLocalWeatherDatabase::get(const Point3D& p) const
199 unsigned int a = AreaWith(p);
201 return WeatherAreas[a-1].get(p.elev());
202 else //point is outside => ask GlobalWeatherDatabase
203 return global->get(p);
206 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
208 Point3D temp(p[0], p[1], p[2]);
210 unsigned int a = AreaWith(temp);
212 return WeatherAreas[a-1].get(temp.elev());
213 else //point is outside => ask GlobalWeatherDatabase
214 return global->get(temp);
217 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
219 Point3D temp(p[0], p[1], 0.0);
221 unsigned int a = AreaWith(temp);
223 return WeatherAreas[a-1].get();
224 else //point is outside => ask GlobalWeatherDatabase
225 return global->get(p);
228 WeatherPrecition FGLocalWeatherDatabase::getAirDensity(const Point3D& p) const
230 FGPhysicalProperty dummy;
231 unsigned int a = AreaWith(p);
233 dummy = WeatherAreas[a-1].get(p.elev());
234 else //point is outside => ask GlobalWeatherDatabase
235 dummy = global->get(p);
238 (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) /
239 (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
242 WeatherPrecition FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
244 Point3D temp(p[0], p[1], p[2]);
246 FGPhysicalProperty dummy;
247 unsigned int a = AreaWith(temp);
249 dummy = WeatherAreas[a-1].get(temp.elev());
250 else //point is outside => ask GlobalWeatherDatabase
251 dummy = global->get(temp);
254 (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) /
255 (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
258 /****************************************************************************/
259 /* Add a weather feature at the point p and surrounding area */
260 /****************************************************************************/
261 void FGLocalWeatherDatabase::addWind(const WeatherPrecition alt, const Point3D& x, const Point2D& p)
263 unsigned int a = AreaWith(p);
265 WeatherAreas[a-1].addWind(alt, x);
268 void FGLocalWeatherDatabase::addTurbulence(const WeatherPrecition alt, const Point3D& x, const Point2D& p)
270 unsigned int a = AreaWith(p);
272 WeatherAreas[a-1].addTurbulence(alt, x);
275 void FGLocalWeatherDatabase::addTemperature(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
277 unsigned int a = AreaWith(p);
279 WeatherAreas[a-1].addTemperature(alt, x);
282 void FGLocalWeatherDatabase::addAirPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
284 unsigned int a = AreaWith(p);
286 WeatherAreas[a-1].addAirPressure(alt, x);
289 void FGLocalWeatherDatabase::addVaporPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
291 unsigned int a = AreaWith(p);
293 WeatherAreas[a-1].addVaporPressure(alt, x);
296 void FGLocalWeatherDatabase::addCloud(const WeatherPrecition alt, const FGCloudItem& x, const Point2D& p)
298 unsigned int a = AreaWith(p);
300 WeatherAreas[a-1].addCloud(alt, x);
303 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecition& x, const Point2D& p)
305 unsigned int a = AreaWith(p);
307 WeatherAreas[a-1].setSnowRainIntensity(x);
310 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType& x, const Point2D& p)
312 unsigned int a = AreaWith(p);
314 WeatherAreas[a-1].setSnowRainType(x);
317 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecition& x, const Point2D& p)
319 unsigned int a = AreaWith(p);
321 WeatherAreas[a-1].setLightningProbability(x);
324 void FGLocalWeatherDatabase::addProperties(const FGPhysicalProperties2D& x)
326 if (DatabaseStatus==use_global)
330 //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
331 //changes my voronoi diagram but I don't update it! instead I'm changing one local value
332 //that could be anywhere!!
333 //This only *might* work when the plane moves so far so fast that the diagram gets new
335 unsigned int a = AreaWith(x.p);
337 WeatherAreas[a-1].setStoredWeather(x);
341 unsigned int a = AreaWith(x.p);
343 WeatherAreas[a-1].setStoredWeather(x);
347 void FGLocalWeatherDatabase::setProperties(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 fgUpdateWeatherDatabase(void)
372 //cerr << "FGLocalWeatherDatabase::update()\n";
373 WeatherDatabase->update( Point3D(
374 current_aircraft.fdm_state->get_Latitude(),
375 current_aircraft.fdm_state->get_Longitude(),
376 current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER) );