]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGLocalWeatherDatabase.cpp
aa2c0229066a6bf3b80deb7f0051c7de4162ccf0
[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 WeatherPrecition FGLocalWeatherDatabase::getAirDensity(const Point3D& p) const
205 {
206     FGPhysicalProperty dummy;
207     unsigned int a = AreaWith(p);
208     if (a != 0)
209         dummy = WeatherAreas[a-1].get(p.elev());
210     else    //point is outside => ask GlobalWeatherDatabase
211         dummy = global->get(p);
212
213     return 
214         (dummy.AirPressure*FG_WEATHER_DEFAULT_AIRDENSITY*FG_WEATHER_DEFAULT_TEMPERATURE) / 
215         (dummy.Temperature*FG_WEATHER_DEFAULT_AIRPRESSURE);
216 }
217
218
219 /****************************************************************************/
220 /* Add a weather feature at the point p and surrounding area                */
221 /****************************************************************************/
222 void FGLocalWeatherDatabase::addWind(const FGWindItem& x, const Point2D& p)
223 {
224     unsigned int a = AreaWith(p);
225     if (a != 0)
226         WeatherAreas[a-1].addWind(x);
227 }
228
229 void FGLocalWeatherDatabase::addTurbulence(const FGTurbulenceItem& x, const Point2D& p)
230 {
231     unsigned int a = AreaWith(p);
232     if (a != 0)
233         WeatherAreas[a-1].addTurbulence(x);
234 }
235
236 void FGLocalWeatherDatabase::addTemperature(const FGTemperatureItem& x, const Point2D& p)
237 {
238     unsigned int a = AreaWith(p);
239     if (a != 0)
240         WeatherAreas[a-1].addTemperature(x);
241 }
242
243 void FGLocalWeatherDatabase::addAirPressure(const FGAirPressureItem& x, const Point2D& p)
244 {
245     unsigned int a = AreaWith(p);
246     if (a != 0)
247         WeatherAreas[a-1].addAirPressure(x);
248 }
249
250 void FGLocalWeatherDatabase::addVaporPressure(const FGVaporPressureItem& x, const Point2D& p)
251 {
252     unsigned int a = AreaWith(p);
253     if (a != 0)
254         WeatherAreas[a-1].addVaporPressure(x);
255 }
256
257 void FGLocalWeatherDatabase::addCloud(const FGCloudItem& x, const Point2D& p)
258 {
259     unsigned int a = AreaWith(p);
260     if (a != 0)
261         WeatherAreas[a-1].addCloud(x);
262 }
263
264 void FGLocalWeatherDatabase::setSnowRainIntensity(const WeatherPrecition& x, const Point2D& p)
265 {
266     unsigned int a = AreaWith(p);
267     if (a != 0)
268         WeatherAreas[a-1].setSnowRainIntensity(x);
269 }
270
271 void FGLocalWeatherDatabase::setSnowRainType(const SnowRainType& x, const Point2D& p)
272 {
273     unsigned int a = AreaWith(p);
274     if (a != 0)
275         WeatherAreas[a-1].setSnowRainType(x);
276 }
277
278 void FGLocalWeatherDatabase::setLightningProbability(const WeatherPrecition& x, const Point2D& p)
279 {
280     unsigned int a = AreaWith(p);
281     if (a != 0)
282         WeatherAreas[a-1].setLightningProbability(x);
283 }
284
285 void FGLocalWeatherDatabase::addProperties(const FGPhysicalProperties2D& x)
286 {
287     if (DatabaseStatus==use_global)
288     {
289         global->add(x);
290
291         //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
292         //changes my voronoi diagram but I don't update it! instead I'm changing one local value
293         //that could be anywhere!!
294         //This only *might* work when the plane moves so far so fast that the diagram gets new
295         //calculated soon...
296         unsigned int a = AreaWith(x.p);
297         if (a != 0)
298             WeatherAreas[a-1].setStoredWeather(x);
299     }
300     else
301     {
302         unsigned int a = AreaWith(x.p);
303         if (a != 0)
304             WeatherAreas[a-1].setStoredWeather(x);
305     }
306 }
307
308 void FGLocalWeatherDatabase::setProperties(const FGPhysicalProperties2D& x)
309 {
310     if (DatabaseStatus==use_global)
311     {
312         global->change(x);
313
314         //BAD, BAD, BAD thing I'm doing here: I'm adding to the global database a point that
315         //changes my voronoi diagram but I don't update it! Instead I'm changing one local value
316         //that could be anywhere!!
317         //This only *might* work when the plane moves so far so fast that the diagram gets newly
318         //calculated soon...
319         unsigned int a = AreaWith(x.p);
320         if (a != 0)
321             WeatherAreas[a-1].setStoredWeather(x);
322     }
323     else
324     {
325         unsigned int a = AreaWith(x.p);
326         if (a != 0)
327             WeatherAreas[a-1].setStoredWeather(x);
328     }
329 }
330
331 void fgUpdateWeatherDatabase(void)
332 {
333     //cerr << "FGLocalWeatherDatabase::update()\n";
334     WeatherDatabase->update( Point3D(
335         current_aircraft.fdm_state->get_Latitude(),
336         current_aircraft.fdm_state->get_Longitude(),
337         current_aircraft.fdm_state->get_Altitude() * FEET_TO_METER) );
338 }
339