100 _metarValidNode( rootNode->getNode(
"valid", true ) ),
101 _station_elevation(0.0),
102 _station_latitude(0.0),
103 _station_longitude(0.0),
104 _min_visibility(16000.0),
105 _max_visibility(16000.0),
107 _base_wind_range_from(0),
108 _base_wind_range_to(0),
110 _wind_from_north_fps(0.0),
111 _wind_from_east_fps(0.0),
117 _sea_level_temperature(0.0),
118 _sea_level_dewpoint(0.0),
119 _sea_level_pressure(29.92),
132 coverage_string.push_back(SGCloudLayer::SG_CLOUD_CLEAR_STRING);
133 coverage_string.push_back(SGCloudLayer::SG_CLOUD_FEW_STRING);
134 coverage_string.push_back(SGCloudLayer::SG_CLOUD_SCATTERED_STRING);
135 coverage_string.push_back(SGCloudLayer::SG_CLOUD_BROKEN_STRING);
136 coverage_string.push_back(SGCloudLayer::SG_CLOUD_OVERCAST_STRING);
139 _metarValidNode->setBoolValue(
false );
141 _tiedProperties.Tie(
"data",
this, &MetarProperties::get_metar, &MetarProperties::set_metar );
142 _tiedProperties.Tie(
"station-id",
this, &MetarProperties::get_station_id, &MetarProperties::set_station_id );
146 _tiedProperties.Tie(
"station-magnetic-variation-deg",
this, &MetarProperties::get_magnetic_variation_deg );
147 _tiedProperties.Tie(
"station-magnetic-dip-deg",
this, &MetarProperties::get_magnetic_dip_deg );
152 _tiedProperties.Tie(
"base-wind-speed-kt",
this, &MetarProperties::get_wind_speed, &MetarProperties::set_wind_speed );
153 _tiedProperties.Tie(
"base-wind-dir-deg",
this, &MetarProperties::get_base_wind_dir, &MetarProperties::set_base_wind_dir );
154 _tiedProperties.Tie(
"base-wind-from-north-fps",
this, &MetarProperties::get_wind_from_north_fps, &MetarProperties::set_wind_from_north_fps );
155 _tiedProperties.Tie(
"base-wind-from-east-fps",
this, &MetarProperties::get_wind_from_east_fps, &MetarProperties::set_wind_from_east_fps );
161 _tiedProperties.Tie(
"temperature-sea-level-degc", &_sea_level_temperature );
173 _tiedProperties.Tie(
"description",
this, &MetarProperties::get_description );
235 _metarData = _metar->getDataString();
237 const std::vector<string> weather = m->getWeather();
238 for( std::vector<string>::const_iterator it = weather.begin(); it != weather.end(); ++it ) {
239 if( !_decoded.empty() ) _decoded.append(
", ");
240 _decoded.append(*it);
243 _min_visibility = m->getMinVisibility().getVisibility_m();
244 _max_visibility = m->getMaxVisibility().getVisibility_m();
246 const SGMetarVisibility *dirvis = m->getDirVisibility();
247 for (
int i = 0;
i < 8;
i++, dirvis++) {
248 SGPropertyNode *vis = _rootNode->getChild(
"visibility",
i,
true);
249 double v = dirvis->getVisibility_m();
251 vis->setDoubleValue(
"min-m", v);
252 vis->setDoubleValue(
"max-m", v);
255 set_base_wind_dir(m->getWindDir());
256 _base_wind_range_from = m->getWindRangeFrom();
257 _base_wind_range_to = m->getWindRangeTo();
258 set_wind_speed(m->getWindSpeed_kt());
260 _gusts = m->getGustSpeed_kt();
261 _temperature = m->getTemperature_C();
262 _dewpoint = m->getDewpoint_C();
263 _humidity = m->getRelHumidity();
264 _pressure = m->getPressure_inHg();
272 SGGeod pos = SGGeod::fromDeg(
282 _station_latitude = towerPosition.getLatitudeDeg();
283 _station_longitude = towerPosition.getLongitudeDeg();
284 _station_id = a->
ident();
286 _station_elevation =
fgGetDouble(
"/position/ground-elev-m", 0.0 ) * SG_METER_TO_FEET;
287 _station_latitude =
fgGetDouble(
"/position/latitude-deg", 0.0 );
288 _station_longitude =
fgGetDouble(
"/position/longitude-deg", 0.0 );
289 _station_id =
"XXXX";
302 double elevation_m = _station_elevation * SG_FEET_TO_METER;
314 for(
unsigned i = 0;
i < 3;
i++ ) {
315 SGPropertyNode_ptr n = _rootNode->getChild(
"weather",
i,
true );
316 std::vector<struct SGMetar::Weather> weather = m->getWeather2();
317 struct SGMetar::Weather * w =
i < weather.size() ? &weather[
i] : NULL;
318 n->getNode(
"intensity",
true)->setIntValue( w != NULL ? w->intensity : 0 );
319 n->getNode(
"vincinity",
true)->setBoolValue( w != NULL ? w->vincinity :
false );
320 for(
unsigned j = 0; j < 3; j++ ) {
322 const string & phenomenon = w != NULL && j < w->phenomena.size() ? w->phenomena[j].c_str() :
"";
323 n->getChild(
"phenomenon", j,
true )->setStringValue( phenomenon );
325 const string & description = w != NULL && j < w->descriptions.size() ? w->descriptions[j].c_str() :
"";
326 n->getChild(
"description", j,
true )->setStringValue( description );
330 if( phenomenon ==
"FG" ) isFG =
true;
331 if( phenomenon ==
"HZ" ) isHZ =
true;
332 if( phenomenon ==
"BR" ) isBR =
true;
333 if( description ==
"MI" ) isMI =
true;
334 if( description ==
"BC" ) isBC =
true;
340 static const char * LAYER =
"layer";
341 SGPropertyNode_ptr cloudsNode = _rootNode->getNode(
"clouds",
true );
342 const std::vector<SGMetarCloud> & metarClouds = m->getClouds();
343 unsigned layerOffset = 0;
346 bool setGroundCloudLayer = _rootNode->getBoolValue(
"set-ground-cloud-layer",
false ) &&
347 !
fgGetBool(
"/sim/rendering/clouds3d-enable",
false);
352 SGMetarCloud::Coverage coverageBelow = SGMetarCloud::COVERAGE_NIL;
354 if( setGroundCloudLayer ) {
359 const double LAYER_BOTTOM_STATION_OFFSET =
360 fgGetDouble(
"/environment/params/fog-mist-haze-layer/offset-from-station-elevation-ft", -200 );
362 SGMetarCloud::Coverage coverage = SGMetarCloud::COVERAGE_NIL;
363 double thickness = 0;
367 coverage = SGMetarCloud::getCoverage( isBC ?
368 fgGetString(
"/environment/params/fog-mist-haze-layer/fog-bc-2dlayer-coverage", SGMetarCloud::COVERAGE_SCATTERED_STRING ) :
369 fgGetString(
"/environment/params/fog-mist-haze-layer/fog-2dlayer-coverage", SGMetarCloud::COVERAGE_BROKEN_STRING )
373 fgGetDouble(
"/environment/params/fog-mist-haze-layer/fog-shallow-thickness-ft",30) - LAYER_BOTTOM_STATION_OFFSET :
374 fgGetDouble(
"/environment/params/fog-mist-haze-layer/fog-thickness-ft",500) - LAYER_BOTTOM_STATION_OFFSET;
375 alpha =
fgGetDouble(
"/environment/params/fog-mist-haze-layer/fog-2dlayer-alpha", 1.0);
377 coverage = SGMetarCloud::getCoverage(
fgGetString(
"/environment/params/fog-mist-haze-layer/mist-2dlayer-coverage", SGMetarCloud::COVERAGE_OVERCAST_STRING));
378 thickness =
fgGetDouble(
"/environment/params/fog-mist-haze-layer/mist-thickness-ft",2000) - LAYER_BOTTOM_STATION_OFFSET;
379 alpha =
fgGetDouble(
"/environment/params/fog-mist-haze-layer/mist-2dlayer-alpha",0.8);
381 coverage = SGMetarCloud::getCoverage(
fgGetString(
"/environment/params/fog-mist-haze-layer/mist-2dlayer-coverage", SGMetarCloud::COVERAGE_OVERCAST_STRING));
382 thickness =
fgGetDouble(
"/environment/params/fog-mist-haze-layer/haze-thickness-ft",2000) - LAYER_BOTTOM_STATION_OFFSET;
383 alpha =
fgGetDouble(
"/environment/params/fog-mist-haze-layer/haze-2dlayer-alpha",0.6);
386 if( coverage != SGMetarCloud::COVERAGE_NIL ) {
389 if( metarClouds.size() > 0 && metarClouds[0].getCoverage() != SGMetarCloud::COVERAGE_CLEAR )
390 thickness = metarClouds[0].getAltitude_ft() - LAYER_BOTTOM_STATION_OFFSET - 1;
392 SGPropertyNode_ptr layerNode = cloudsNode->getChild(LAYER, 0,
true );
393 layerNode->setDoubleValue(
"coverage-type", SGCloudLayer::getCoverageType(
coverage_string[coverage]) );
395 layerNode->setDoubleValue(
"elevation-ft", _station_elevation + LAYER_BOTTOM_STATION_OFFSET );
396 layerNode->setDoubleValue(
"thickness-ft", thickness );
397 layerNode->setDoubleValue(
"visibility-m", _min_visibility );
398 layerNode->setDoubleValue(
"alpha", alpha );
399 _min_visibility = _max_visibility =
400 fgGetDouble(
"/environment/params/fog-mist-haze-layer/visibility-above-layer-m",20000.0);
403 coverageBelow = coverage;
407 for(
unsigned i = 0;
i < 5-layerOffset;
i++ ) {
408 SGPropertyNode_ptr layerNode = cloudsNode->getChild(LAYER,
i+layerOffset,
true );
409 SGMetarCloud::Coverage coverage =
i < metarClouds.size() ? metarClouds[
i].getCoverage() : SGMetarCloud::COVERAGE_CLEAR;
410 if (coverage == SGMetarCloud::COVERAGE_NIL) {
411 coverage = coverageBelow;
413 coverageBelow = coverage;
416 if (coverage == SGMetarCloud::COVERAGE_NIL) {
417 SG_LOG(SG_ENVIRONMENT, SG_WARN,
"METAR: skipping cloud layer " <<
i <<
" because no coverage is set");
422 i >= metarClouds.size() || coverage == SGMetarCloud::COVERAGE_CLEAR ?
424 metarClouds[
i].getAltitude_ft() + _station_elevation;
426 layerNode->setDoubleValue(
"alpha", 1.0 );
428 layerNode->setDoubleValue(
"coverage-type", SGCloudLayer::getCoverageType(
coverage_string[coverage]) );
429 layerNode->setDoubleValue(
"elevation-ft", elevation );
431 layerNode->setDoubleValue(
"span-m", 40000 );
432 layerNode->setDoubleValue(
"visibility-m", 50.0 );
436 _rain = m->getRain();
437 _hail = m->getHail();
438 _snow = m->getSnow();
439 _snow_cover = m->getSnowCover();
441 _hour = m->getHour();
442 _minute = m->getMinute();
443 _cavok = m->getCAVOK();
445 _metarValidNode->setBoolValue(
true);
446 _description = m->getDescription(-1);