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