]> git.mxchange.org Git - flightgear.git/blob - src/Environment/fgmetar.cxx
Fix stray back-button in Qt launcher
[flightgear.git] / src / Environment / fgmetar.cxx
1 // metar interface class
2 //
3 // Written by Melchior FRANZ, started January 2005.
4 //
5 // Copyright (C) 2005  Melchior FRANZ - mfranz@aon.at
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 /**
24  * @file fgmetar.cxx
25  * Implements FGMetar class that inherits from SGMetar.
26  *
27  * o provide defaults for unset values
28  * o interpolate/randomize data (GREATER_THAN)
29  * o derive additional values (time, age, snow cover)
30  * o consider minimum identifier (CAVOK, mil. color codes)
31  *
32  * TODO
33  * - NSC & mil. color codes
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <simgear/math/sg_random.h>
40 #include <simgear/timing/sg_time.hxx>
41 #include <simgear/timing/lowleveltime.h>
42
43 #include <Main/fg_props.hxx>
44
45 #include "fgmetar.hxx"
46
47
48 FGMetar::FGMetar(const string& icao) :
49         SGMetar(icao),
50         _snow_cover(false)
51 {
52         int i;
53         double d;
54
55         // CAVOK: visibility >= 10km; lowest cloud layer >= 5000 ft; any coverage
56         if (getCAVOK()) {
57                 if (_min_visibility.getVisibility_m() == SGMetarNaN)
58                         _min_visibility.set(12000.0);
59
60                 if (_max_visibility.getVisibility_m() == SGMetarNaN)
61                         _min_visibility.set(12000.0);
62
63                 vector<SGMetarCloud> cv = _clouds;;
64                 if (cv.empty()) {
65                         SGMetarCloud cl;
66                         cl.set(5500 * SG_FEET_TO_METER, SGMetarCloud::COVERAGE_SCATTERED);
67                         _clouds.push_back(cl);
68                 }
69         }
70
71         // visibility
72         d = _min_visibility.getVisibility_m();
73         if (d == SGMetarNaN)
74                 d = 10000.0;
75         if (_min_visibility.getModifier() == SGMetarVisibility::GREATER_THAN)
76                 d += 15000.0;// * sg_random();
77         _min_visibility.set(d);
78
79         if (_max_visibility.getVisibility_m() == SGMetarNaN)
80                 _max_visibility.set(d);
81
82         for (i = 0; i < 8; i++) {
83                 d = _dir_visibility[i].getVisibility_m();
84                 if (d == SGMetarNaN)
85                         _dir_visibility[i].set(10000.0);
86                 if (_dir_visibility[i].getModifier() == SGMetarVisibility::GREATER_THAN)
87                         d += 15000.0;// * sg_random();
88                 _dir_visibility[i].set(d);
89         }
90
91         // wind
92         if (_wind_dir == -1) {
93                 if (_wind_range_from == -1) {
94                         _wind_dir = 0;
95                         _wind_range_from = 0;
96                         _wind_range_to = 359;
97                 } else {
98                         _wind_dir = (_wind_range_from + _wind_range_to) / 2;
99                 }
100         } else if (_wind_range_from == -1) {
101                 _wind_range_from = _wind_range_to = _wind_dir;
102         }
103
104         if (_wind_speed == SGMetarNaN)
105                 _wind_speed = 0.0;
106         if (_gust_speed == SGMetarNaN)
107                 _gust_speed = 0.0;
108
109         // clouds
110         vector<SGMetarCloud> cv = _clouds;
111         vector<SGMetarCloud>::iterator cloud, cv_end = cv.end();
112
113         for (i = 0, cloud = cv.begin(); cloud != cv_end; ++cloud, i++) {
114                 SGMetarCloud::Coverage cov = cloud->getCoverage();
115                 if (cov == SGMetarCloud::COVERAGE_NIL)
116                         cov = SGMetarCloud::COVERAGE_CLEAR;
117
118                 double alt = cloud->getAltitude_ft();
119                 if (alt == SGMetarNaN)
120                         alt = -9999;
121
122                 cloud->set(alt, cov);
123         }
124
125
126         // temperature/pressure
127         if (_temp == SGMetarNaN)
128                 _temp = 15.0;
129
130         if (_dewp == SGMetarNaN)
131                 _dewp = 0.0;
132
133         if (_pressure == SGMetarNaN)
134                 _pressure = 30.0 * SG_INHG_TO_PA;
135
136         // snow cover
137         map<string, SGMetarRunway> rm = getRunways();
138         map<string, SGMetarRunway>::const_iterator runway, rm_end = rm.end();
139         for (runway = rm.begin(); runway != rm_end; ++runway) {
140                 SGMetarRunway rwy = runway->second;
141                 if (rwy.getDeposit() >= 3 ) {
142                         _snow_cover = true;
143                         break;
144                 }
145         }
146         if (_temp < 5.0 && _snow)
147                 _snow_cover = true;
148         if (_temp < 1.0 && getRelHumidity() > 80)
149                 _snow_cover = true;
150
151         _time = sgTimeGetGMT(_year - 1900, _month - 1, _day, _hour, _minute, 0);
152
153         SG_LOG(SG_ENVIRONMENT, SG_INFO, _data);
154         if (_x_proxy)
155                 SG_LOG(SG_ENVIRONMENT, SG_INFO, "METAR from proxy");
156         else
157                 SG_LOG(SG_ENVIRONMENT, SG_INFO, "METAR from weather.noaa.gov");
158 }
159
160
161 long FGMetar::getAge_min() const
162 {
163         time_t now = _x_proxy ? _rq_time : sgGMTime();
164         return (now - _time) / 60;
165 }
166