]> git.mxchange.org Git - flightgear.git/blob - src/WeatherCM/FGGlobalWeatherDatabase.cpp
Various SGI portability tweaks.
[flightgear.git] / src / WeatherCM / FGGlobalWeatherDatabase.cpp
1 /*****************************************************************************
2
3  Module:       FGGlobalWeatherDatabase.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 global weather
30 This database is only called by the local database and by the weather
31 simulator driving this database
32
33 HISTORY
34 ------------------------------------------------------------------------------
35 28.05.1999 Christian Mayer      Created
36 16.06.1999 Durk Talsma          Portability for Linux
37 20.06.1999 Christian Mayer      added lots of consts
38 *****************************************************************************/
39
40 /****************************************************************************/
41 /* INCLUDES                                                                 */
42 /****************************************************************************/
43 #include "FGGlobalWeatherDatabase.h"
44
45 /****************************************************************************/
46 /********************************** CODE ************************************/
47 /****************************************************************************/
48
49 /****************************************************************************/
50 /* Interpolate p which lies inside the triangle x1, x2, x3                  */
51 /*                                                                          */
52 /*  x3\                 Do this by calulating q and linear interpolate its  */
53 /*   |\ \               value as it's laying between x1 and x2.             */
54 /*   | \  \             Then interpolate p as it lays between p and x3      */
55 /*   |  \   \                                                               */
56 /*   |   p    \         Advantages: p has exactly the value of a corner     */
57 /*   |    \     \                   when it's laying on it.                 */
58 /*   |     \      \                 If p isn't in the triangle the algoritm */
59 /*  x1------q------x2               extrapolates it's value                 */
60 /****************************************************************************/
61 template<class P, class V>
62 V triangle_interpolate(const P& x1, const V& v1, const P& x2, const V& v2, const P& x3, const V& v3, const P& p)
63 {
64     P q;
65     V q_value;
66     
67     q = x1 + (x2 - x1)*( ((x3-x1).x()*(x1-x2).y() - (x1-x2).x()*(x3-x1).y())/((p-x3).x()*(x2-x1).y() - (x2-x1).x()*(p-x3).y()) );
68     
69     q_value = v1 + (v2 - v1) * (x1.distance3D(q) / x1.distance3D(x2));
70     
71     return q_value + (v3 - q_value) * (q.distance3D(p) / q.distance3D(x3));
72 }
73
74 /****************************************************************************/
75 /* Constructor and Destructor                                               */
76 /****************************************************************************/
77 FGGlobalWeatherDatabase::FGGlobalWeatherDatabase(const FGGlobalWeatherDatabaseStatus& s)
78 {
79     DatabaseStatus = s; 
80 }
81
82 FGGlobalWeatherDatabase::~FGGlobalWeatherDatabase()
83 {
84 }
85
86 /****************************************************************************/
87 /* Get the physical properties on the specified point p                     */
88 /* do this by interpolating between the 3 closest points                    */
89 /****************************************************************************/
90 FGPhysicalProperties FGGlobalWeatherDatabase::get(const Point2D& p) const
91 {
92     WeatherPrecition distance[3];               //store the 3 closest distances
93     FGPhysicalProperties2DVectorConstIt iterator[3];    //and the coresponding iterators
94     WeatherPrecition d;
95     
96     distance[0] = 9.46e15;      //init with a distance that every calculated
97     distance[1] = 9.46e15;      //distance is guranteed to be shorter as
98     distance[2] = 9.46e15;      //9.46e15 metres are 1 light year...
99     
100     for (FGPhysicalProperties2DVectorConstIt it=database.begin(); it!=database.end(); it++)
101     {   //go through the whole database
102         d = it->p.distance2Dsquared(p);
103         
104         if (d<distance[0])
105         {
106             distance[2] = distance[1]; distance[1] = distance[0]; distance[0] = d;
107             iterator[2] = iterator[1]; iterator[1] = iterator[0]; iterator[0] = it;
108             //NOTE: The last line causes a warning that an unitialiced variable
109             //is used. You can ignore this warning here.
110         }
111         else if (d<distance[1])
112         {
113             distance[2] = distance[1]; distance[1] = d;
114             iterator[2] = iterator[1]; iterator[1] = it;
115         } 
116         else if (d<distance[2])
117         {
118             distance[2] = d;
119             iterator[2] = it;
120         }
121     }
122     
123     //now I've got the closest entry in xx[0], the 2nd closest in xx[1] and the
124     //3rd in xx[2];
125     
126     //interpolate now:
127     return triangle_interpolate(
128         iterator[0]->p, (FGPhysicalProperties)*iterator[0],
129         iterator[1]->p, (FGPhysicalProperties)*iterator[1],
130         iterator[2]->p, (FGPhysicalProperties)*iterator[2], p);
131 }
132
133 /****************************************************************************/
134 /* update the database. Since the last call we had dt seconds               */
135 /****************************************************************************/
136 void FGGlobalWeatherDatabase::update(const WeatherPrecition& dt)
137 {
138     // I've got nothing to update here (yet...)
139 }
140
141 /****************************************************************************/
142 /* Add a physical property on the specified point p                         */
143 /****************************************************************************/
144 void FGGlobalWeatherDatabase::add(const Point2D& p, const FGPhysicalProperties& x)
145 {
146     FGPhysicalProperties2D e;
147     
148     e.p = p;
149     
150     e.Wind = x.Wind;    
151     e.Turbulence = x.Turbulence;          
152     e.Temperature = x.Temperature;       
153     e.AirPressure = x.AirPressure;        
154     e.VaporPressure = x.VaporPressure;
155     
156     e.Clouds = x.Clouds;                  
157     e.SnowRainIntensity = x.SnowRainIntensity;    
158     e.snowRainType = x.snowRainType;        
159     e.LightningProbability = x.LightningProbability;
160     
161     database.push_back(e);
162 }
163
164 /****************************************************************************/
165 /* Change the closest physical property to p. If p is further away than     */
166 /* tolerance I'm returning false otherwise true                             */
167 /****************************************************************************/
168 bool FGGlobalWeatherDatabase::change(const FGPhysicalProperties2D& p, const WeatherPrecition& tolerance)
169 {
170     for (FGPhysicalProperties2DVectorIt it = database.begin(); it != database.end(); it++)
171     {
172         if (it->p.distance3Dsquared(p.p) < (tolerance*tolerance))
173         {   //assume that's my point
174             (*it) = p;
175             return true;
176         }
177     }
178     
179     return false;
180 }
181
182 /****************************************************************************/
183 /* Get all, but at least min, stored point in the circle around p with the  */
184 /* radius r                                                                 */
185 /****************************************************************************/
186 FGPhysicalProperties2DVector FGGlobalWeatherDatabase::getAll(const Point2D& p, const WeatherPrecition& r, const unsigned int& min)
187 {
188     FGPhysicalProperties2DVector ret_list;
189     
190     if ((DatabaseStatus == FGGlobalWeatherDatabase_only_static)
191         ||(DatabaseStatus == FGGlobalWeatherDatabase_working) )
192     {   //doest it make sense?
193         
194         FGPhysicalProperties2DVectorIt *it;         //store the closest entries
195         WeatherPrecition *d;
196         unsigned int act_it = 0;
197         int i;
198         
199         it = new FGPhysicalProperties2DVectorIt[min+1];
200         d = new WeatherPrecition[min+1];
201         
202         for (it[0]=database.begin(); it[act_it]!=database.end(); it[act_it]++)
203         {       //go through the whole database
204             d[act_it] = it[act_it]->p.distance2Dsquared(p);
205             
206             if (r >= d[act_it])
207             {   //add it
208                 ret_list.push_back(*it[act_it]);
209             }
210             else
211             {
212                 if (act_it>0)
213                 {   //figure out if this distance belongs to the closest ones
214                     WeatherPrecition dummy;
215                     FGPhysicalProperties2DVectorIt dummyIt;
216                     
217                     for (i = act_it++; i >= 0;)
218                     {
219                         if (d[i] >= d[--i])
220                         {
221                             act_it--;
222                             break;  //nope => stop
223                         }
224                         
225                         //swap both
226                         dummy =d[i]; d[i] = d[i+1]; d[i+1] = dummy;
227                         dummyIt = it[i]; it[i] = it[i+1]; it[i+1] = dummyIt;
228                     }
229                 }
230             }
231         }
232         
233         if (ret_list.size()<min)
234         {
235             for(i = 0; (i < (min - ret_list.size())) && (ret_list.size() < database.size()); i++)
236                 ret_list.push_back(*it[i]);
237         }
238         
239         delete d;
240         delete it;
241     }
242     
243     return ret_list;
244 }
245