// metar interface class // // Written by Melchior FRANZ, started January 2005. // // Copyright (C) 2005 Melchior FRANZ - mfranz@aon.at // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // $Id$ /** * @file fgmetar.cxx * Implements FGMetar class that inherits from SGMetar. * * o provide defaults for unset values * o interpolate/randomize data (GREATER_THAN) * o derive additional values (time, age, snow cover) * o consider minimum identifier (CAVOK, mil. color codes) * * TODO * - NSC & mil. color codes */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include
#include "fgmetar.hxx" FGMetar::FGMetar(const string& icao, const string& proxy, const string& port, const string& auth) : SGMetar(icao, proxy, port, auth, _rq_time = globals->get_time_params()->get_cur_time()), _snow_cover(false) { int i; double d; // CAVOK: visibility >= 10km; lowest cloud layer >= 5000 ft; any coverage if (getCAVOK()) { if (_min_visibility.getVisibility_m() == SGMetarNaN) _min_visibility.set(12000.0); if (_max_visibility.getVisibility_m() == SGMetarNaN) _min_visibility.set(12000.0); vector cv = _clouds;; if (!cv.size()) { SGMetarCloud cl; cl.set(5500 * SG_FEET_TO_METER, 2); _clouds.push_back(cl); } } // visibility d = _min_visibility.getVisibility_m(); if (d == SGMetarNaN) d = 10000.0; if (_min_visibility.getModifier() == SGMetarVisibility::GREATER_THAN) d += 15000.0;// * sg_random(); _min_visibility.set(d); if (_max_visibility.getVisibility_m() == SGMetarNaN) _max_visibility.set(d); for (i = 0; i < 8; i++) { d = _dir_visibility[i].getVisibility_m(); if (d == SGMetarNaN) _dir_visibility[i].set(10000.0); if (_dir_visibility[i].getModifier() == SGMetarVisibility::GREATER_THAN) d += 15000.0;// * sg_random(); _dir_visibility[i].set(d); } // wind if (_wind_dir == -1) { if (_wind_range_from == -1) { _wind_dir = 0; _wind_range_from = 0; _wind_range_to = 359; } else { _wind_dir = (_wind_range_from + _wind_range_to) / 2; } } else if (_wind_range_from == -1) { _wind_range_from = _wind_range_to = _wind_dir; } if (_gust_speed == SGMetarNaN) _gust_speed = 0.0; // clouds vector cv = _clouds; vector::iterator cloud; for (i = 0, cloud = cv.begin(); cloud != cv.end(); cloud++, i++) { int cov = cloud->getCoverage(); if (cov == -1) cov = 0; double alt = cloud->getAltitude_ft(); if (alt == SGMetarNaN) alt = -9999; cloud->set(alt, cov); } // temperature/pressure if (_temp == SGMetarNaN) _temp = 15.0; if (_dewp == SGMetarNaN) _dewp = 0.0; if (_pressure == SGMetarNaN) _pressure = 30.0 * SG_INHG_TO_PA; // snow cover map rm = getRunways(); map::const_iterator runway; for (runway = rm.begin(); runway != rm.end(); runway++) { SGMetarRunway rwy = runway->second; if (rwy.getDeposit() >= 3 ) { _snow_cover = true; break; } } if (_temp < 5.0 && _snow) _snow_cover = true; if (_temp < 1.0 && getRelHumidity() > 80) _snow_cover = true; _time = sgTimeGetGMT(_year - 1900, _month - 1, _day, _hour, _minute, 0); SG_LOG(SG_GENERAL, SG_INFO, _data); if (_x_proxy) SG_LOG(SG_GENERAL, SG_INFO, "METAR from proxy"); else SG_LOG(SG_GENERAL, SG_INFO, "METAR from weather.noaa.gov"); } long FGMetar::getAge_min() const { time_t now = _x_proxy ? _rq_time : time(0); return (now - _time) / 60; }