]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.cpp
7d284e011f4b25696971a7494e8097826cd3d7b3
[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 (vader@t-online.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 *****************************************************************************/
40
41 /****************************************************************************/
42 /* INCLUDES                                                                 */
43 /****************************************************************************/
44 #include "FGLocalWeatherDatabase.h"
45 #include "FGVoronoi.h"
46 #include "fg_constants.h"
47
48 #include <Aircraft/aircraft.hxx>
49 #include <Include/fg_constants.h>
50
51 /****************************************************************************/
52 /********************************** CODE ************************************/
53 /****************************************************************************/
54
55 /****************************************************************************/
56 /* return the index (better: ID) of the area with point p                   */
57 /****************************************************************************/
58 unsigned int FGLocalWeatherDatabase::AreaWith(const Point2D& p) const
59 {
60     
61     for (FGMicroWeatherList::size_type i = 0; i != WeatherAreas.size(); i++)
62     {
63         if (WeatherAreas[i].hasPoint(p) == true)
64             return i+1;
65     }
66
67     return 0;   //nothing found
68 }
69
70 /****************************************************************************/
71 /* make tiles out of points on a 2D plane                                   */
72 /****************************************************************************/
73 void FGLocalWeatherDatabase::tileLocalWeather(const FGPhysicalProperties2DVector& EntryList)
74 {
75     FGVoronoiInputList input;
76
77     for (FGPhysicalProperties2DVector::const_iterator it1 = EntryList.begin(); it1 != EntryList.end(); it1++)
78         input.push_back(FGVoronoiInput(it1->p, *it1));
79
80     FGVoronoiOutputList output = Voronoiate(input);
81
82     for (FGVoronoiOutputList::iterator it2 = output.begin(); it2 != output.end(); it2++)
83         WeatherAreas.push_back(FGMicroWeather(it2->value, it2->boundary));
84 }
85
86 /****************************************************************************/
87 /* Constructor and Destructor                                               */
88 /****************************************************************************/
89 FGLocalWeatherDatabase* FGLocalWeatherDatabase::theFGLocalWeatherDatabase = 0;
90 FGLocalWeatherDatabase *WeatherDatabase;
91
92 FGLocalWeatherDatabase::FGLocalWeatherDatabase(const Point3D& posititon, const WeatherPrecition& visibility, const DatabaseWorkingType& type)
93 {
94     cerr << "Initializing FGLocalWeatherDatabase\n";
95     cerr << "-----------------------------------\n";
96
97     if (theFGLocalWeatherDatabase)
98     {
99         //FG_LOG( FG_GENERAL, FG_ALERT, "Error: only one local weather allowed" );
100         cerr << "Error: only one local weather allowed";
101         exit(-1);
102     }
103
104     setWeatherVisibility(visibility);
105     //WeatherVisibility = visibility;
106     DatabaseStatus = type;
107     global = 0;     //just get sure...
108     last_known_position = posititon;
109
110
111     theFGLocalWeatherDatabase = this;
112
113     switch(DatabaseStatus)
114     {
115     case use_global:
116         {
117             global = new FGGlobalWeatherDatabase;       //initialize GlobalDatabase
118             global->setDatabaseStatus(FGGlobalWeatherDatabase_working);
119             tileLocalWeather(global->getAll(posititon, WeatherVisibility, 3));
120         }
121         break;
122
123     case distant:
124         cerr << "FGLocalWeatherDatabase error: Distant database isn't implemented yet!\n";
125         cerr << "  using random mode instead!\n";
126     case random:
127     case manual:
128     case default_mode:
129         {
130             vector<Point2D> emptyList;
131             WeatherAreas.push_back(FGMicroWeather(FGPhysicalProperties2D(), emptyList));   //in these cases I've only got one tile
132         }
133         break;
134
135     default:
136         cerr << "FGLocalWeatherDatabase error: Unknown database type specified!\n";
137     };
138 }
139
140 FGLocalWeatherDatabase::~FGLocalWeatherDatabase()
141 {
142     //Tidying up:
143
144     //delete every stored area
145     WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
146
147     //delete global database if necessary
148     if (DatabaseStatus == use_global)
149         delete global;
150 }
151
152 /****************************************************************************/
153 /* reset the whole database                                                 */
154 /****************************************************************************/
155 void FGLocalWeatherDatabase::reset(const DatabaseWorkingType& type)
156 {
157     //delete global database if necessary
158     if ((DatabaseStatus == use_global) && (type != use_global))
159         delete global;
160
161     DatabaseStatus = type;
162     if (DatabaseStatus == use_global)
163         tileLocalWeather(global->getAll(last_known_position, WeatherVisibility, 3));
164
165     //delete every stored area
166     WeatherAreas.erase(WeatherAreas.begin(), WeatherAreas.end());
167 }
168
169 /****************************************************************************/
170 /* update the database. Since the last call we had dt seconds               */
171 /****************************************************************************/
172 void FGLocalWeatherDatabase::update(const WeatherPrecition& dt)
173 {
174     if (DatabaseStatus==use_global)
175         global->update(dt);
176 }
177
178 void FGLocalWeatherDatabase::update(const Point3D& p) //position has changed
179 {
180     last_known_position = p;
181     //cerr << "****\nupdate inside\n";
182     //cerr << "Parameter: " << p << "\n";
183     //cerr << "****\n";
184 }
185
186 void FGLocalWeatherDatabase::update(const Point3D& p, const WeatherPrecition& dt)   //time and/or position has changed
187 {
188     last_known_position = p;
189
190     if (DatabaseStatus==use_global)
191         global->update(dt);
192 }
193
194 /****************************************************************************/
195 /* Get the physical properties on the specified point p out of the database */
196 /****************************************************************************/
197 FGPhysicalProperty FGLocalWeatherDatabase::get(const Point3D& p) const
198 {
199     unsigned int a = AreaWith(p);
200     if (a != 0)
201         return WeatherAreas[a-1].get(p.elev());
202     else    //point is outside => ask GlobalWeatherDatabase
203         return global->get(p);
204 }
205
206 FGPhysicalProperty FGLocalWeatherDatabase::get(const sgVec3& p) const
207 {
208     Point3D temp(p[0], p[1], p[2]);
209
210     unsigned int a = AreaWith(temp);
211     if (a != 0)
212         return WeatherAreas[a-1].get(temp.elev());
213     else    //point is outside => ask GlobalWeatherDatabase
214         return global->get(temp);
215 }
216
217 FGPhysicalProperties FGLocalWeatherDatabase::get(const sgVec2& p) const
218 {
219     Point3D temp(p[0], p[1], 0.0);
220
221     unsigned int a = AreaWith(temp);
222     if (a != 0)
223         return WeatherAreas[a-1].get();
224     else    //point is outside => ask GlobalWeatherDatabase
225         return global->get(p);
226 }
227
228 WeatherPrecition FGLocalWeatherDatabase::getAirDensity(const Point3D& p) const
229 {
230     FGPhysicalProperty dummy;
231     unsigned int a = AreaWith(p);
232     if (a != 0)
233         dummy = WeatherAreas[a-1].get(p.elev());
234     else    //point is outside => ask GlobalWeatherDatabase
235         dummy = global->get(p);
236
237     return 
238         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
239         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
240 }
241
242 WeatherPrecition FGLocalWeatherDatabase::getAirDensity(const sgVec3& p) const
243 {
244     Point3D temp(p[0], p[1], p[2]);
245
246     FGPhysicalProperty dummy;
247     unsigned int a = AreaWith(temp);
248     if (a != 0)
249         dummy = WeatherAreas[a-1].get(temp.elev());
250     else    //point is outside => ask GlobalWeatherDatabase
251         dummy = global->get(temp);
252
253     return 
254         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
255         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
256 }
257
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)
262 {
263     unsigned int a = AreaWith(p);
264     if (a != 0)
265         WeatherAreas[a-1].addWind(alt, x);
266 }
267
268 void FGLocalWeatherDatabase::addTurbulence(const WeatherPrecition alt, const Point3D& x, const Point2D& p)
269 {
270     unsigned int a = AreaWith(p);
271     if (a != 0)
272         WeatherAreas[a-1].addTurbulence(alt, x);
273 }
274
275 void FGLocalWeatherDatabase::addTemperature(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
276 {
277     unsigned int a = AreaWith(p);
278     if (a != 0)
279         WeatherAreas[a-1].addTemperature(alt, x);
280 }
281
282 void FGLocalWeatherDatabase::addAirPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
283 {
284     unsigned int a = AreaWith(p);
285     if (a != 0)
286         WeatherAreas[a-1].addAirPressure(alt, x);
287 }
288
289 void FGLocalWeatherDatabase::addVaporPressure(const WeatherPrecition alt, const WeatherPrecition x, const Point2D& p)
290 {
291     unsigned int a = AreaWith(p);
292     if (a != 0)
293         WeatherAreas[a-1].addVaporPressure(alt, x);
294 }
295
296 void FGLocalWeatherDatabase::addCloud(const WeatherPrecition alt, const FGCloudItem& x, const Point2D& p)
297 {
298     unsigned int a = AreaWith(p);
299     if (a != 0)
300         WeatherAreas[a-1].addCloud(alt, x);
301 }
302
303 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecition& x, const Point2D& p)
304 {
305     unsigned int a = AreaWith(p);
306     if (a != 0)
307         WeatherAreas[a-1].setSnowRainIntensity(x);
308 }
309
310 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType& x, const Point2D& p)
311 {
312     unsigned int a = AreaWith(p);
313     if (a != 0)
314         WeatherAreas[a-1].setSnowRainType(x);
315 }
316
317 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecition& x, const Point2D& p)
318 {
319     unsigned int a = AreaWith(p);
320     if (a != 0)
321         WeatherAreas[a-1].setLightningProbability(x);
322 }
323
324 void FGLocalWeatherDatabase::addProperties(const FGPhysicalProperties2D& x)
325 {
326     if (DatabaseStatus==use_global)
327     {
328         global->add(x);
329
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
334         //calculated soon...
335         unsigned int a = AreaWith(x.p);
336         if (a != 0)
337             WeatherAreas[a-1].setStoredWeather(x);
338     }
339     else
340     {
341         unsigned int a = AreaWith(x.p);
342         if (a != 0)
343             WeatherAreas[a-1].setStoredWeather(x);
344     }
345 }
346
347 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
348 {
349     if (DatabaseStatus==use_global)
350     {
351         global->change(x);
352
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
357         //calculated soon...
358         unsigned int a = AreaWith(x.p);
359         if (a != 0)
360             WeatherAreas[a-1].setStoredWeather(x);
361     }
362     else
363     {
364         unsigned int a = AreaWith(x.p);
365         if (a != 0)
366             WeatherAreas[a-1].setStoredWeather(x);
367     }
368 }
369
370 void fgUpdateWeatherDatabase(void)
371 {
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) );
377 }
378