diff --git a/samples/weatherdata/weatherdataprinter.cpp b/samples/weatherdata/weatherdataprinter.cpp index 38da977df..c3629d4fc 100644 --- a/samples/weatherdata/weatherdataprinter.cpp +++ b/samples/weatherdata/weatherdataprinter.cpp @@ -32,33 +32,40 @@ void CWeatherDataPrinter::ps_printWeatherData(const BlackMisc::Weather::CWeather { qtout << "Latitude:" << gridPoint.getPosition().latitude().toQString() << endl; qtout << "Longitude:" << gridPoint.getPosition().longitude().toQString() << endl; + qtout << " Surface Pressure: " << gridPoint.getSurfacePressure().toQString() << endl; CTemperatureLayerList temperatureLayers = gridPoint.getTemperatureLayers(); temperatureLayers.sort([](const CTemperatureLayer &a, const CTemperatureLayer &b) { return a.getLevel() < b.getLevel(); }); - CWindLayerList windLayers = gridPoint.getWindLayers(); - windLayers.sort([](const CWindLayer &a, const CWindLayer &b) { return a.getLevel() < b.getLevel(); }); - - if (temperatureLayers.size() != windLayers.size()) { continue; } - for (int i = 0; i < temperatureLayers.size(); i++) + qtout << " Temperature Layers: " << endl; + for (const auto &temperatureLayer : as_const(temperatureLayers)) { - const CTemperatureLayer temperatureLayer = temperatureLayers[i]; - const CWindLayer windLayer = windLayers[i]; - qtout << " Level: " << temperatureLayer.getLevel().toQString() << endl; - qtout << " Temperature: " << temperatureLayer.getTemperature().toQString() << endl; - qtout << " Relative Humidity: " << temperatureLayer.getRelativeHumidity() << " %" << endl; - qtout << " Wind: " << windLayer.getDirection().toQString() << " at " << windLayer.getSpeed().toQString() << endl; + qtout << " Level: " << temperatureLayer.getLevel().toQString() << endl; + qtout << " Temperature: " << temperatureLayer.getTemperature().toQString() << endl; + qtout << " Relative Humidity: " << temperatureLayer.getRelativeHumidity() << " %" << endl; } qtout << endl; - qtout << " Clouds: " << endl; + CWindLayerList windLayers = gridPoint.getWindLayers(); + windLayers.sort([](const CWindLayer &a, const CWindLayer &b) { return a.getLevel() < b.getLevel(); }); + qtout << " Wind Layers: " << endl; + for (const auto &windLayer : as_const(windLayers)) + { + qtout << " Level: " << windLayer.getLevel().toQString() << endl; + qtout << " Wind: " << windLayer.getDirection().toQString() << " at " << windLayer.getSpeed().toQString() << endl; + } + qtout << endl; + + qtout << " Cloud Layers: " << endl; CCloudLayerList cloudLayers = gridPoint.getCloudLayers(); cloudLayers.sort([](const CCloudLayer &a, const CCloudLayer &b) { return a.getBase() < b.getBase(); }); for (int i = 0; i < cloudLayers.size(); i++) { const CCloudLayer &cloudLayer = cloudLayers[i]; qtout << " Top: " << cloudLayer.getTop().toQString() << endl; + qtout << " Coverage: " << cloudLayer.getCoveragePercent() << " %" << endl; + qtout << " Precipitation type: " << cloudLayer.getPrecipitation() << endl; + qtout << " Precipitation rate: " << cloudLayer.getPrecipitationRate() << endl; qtout << " Base: " << cloudLayer.getBase().toQString() << endl; - qtout << " Coverage: " << cloudLayer.getCoveragePercent() << " %" << endl; } qtout << endl << endl; } diff --git a/src/blackmisc/weather/gridpoint.cpp b/src/blackmisc/weather/gridpoint.cpp index 2d97d33b4..6f020a386 100644 --- a/src/blackmisc/weather/gridpoint.cpp +++ b/src/blackmisc/weather/gridpoint.cpp @@ -30,13 +30,15 @@ namespace BlackMisc const CCloudLayerList &cloudLayers, const CTemperatureLayerList &temperatureLayers, const CVisibilityLayerList &visibilityLayers, - const CWindLayerList &windLayers) : + const CWindLayerList &windLayers, + const CPressure &surfacePressure) : m_identifier(identifier), m_position(position), m_cloudLayers(cloudLayers), m_temperatureLayers(temperatureLayers), m_visibilityLayers(visibilityLayers), - m_windLayers(windLayers) + m_windLayers(windLayers), + m_surfacePressure(surfacePressure) { } void CGridPoint::copyWeatherDataFrom(const CGridPoint &other) @@ -45,6 +47,7 @@ namespace BlackMisc setTemperatureLayers(other.getTemperatureLayers()); setVisibilityLayers(other.getVisibilityLayers()); setWindLayers(other.getWindLayers()); + setSurfacePressure(other.getSurfacePressure()); } CVariant CGridPoint::propertyByIndex(const BlackMisc::CPropertyIndex &index) const @@ -63,6 +66,8 @@ namespace BlackMisc return CVariant::fromValue(m_temperatureLayers); case IndexWindLayers: return CVariant::fromValue(m_windLayers); + case IndexSurfacePressure: + return CVariant::fromValue(m_surfacePressure); default: return CValueObject::propertyByIndex(index); } @@ -80,7 +85,6 @@ namespace BlackMisc case IndexPosition: setPosition(variant.value()); break; - break; case IndexCloudLayers: setCloudLayers(variant.value()); break; @@ -90,6 +94,9 @@ namespace BlackMisc case IndexWindLayers: setWindLayers(variant.value()); break; + case IndexSurfacePressure: + setSurfacePressure(variant.value()); + break; default: CValueObject::setPropertyByIndex(variant, index); break; diff --git a/src/blackmisc/weather/gridpoint.h b/src/blackmisc/weather/gridpoint.h index d5e4809f1..9754361de 100644 --- a/src/blackmisc/weather/gridpoint.h +++ b/src/blackmisc/weather/gridpoint.h @@ -20,6 +20,7 @@ #include "blackmisc/weather/temperaturelayerlist.h" #include "blackmisc/weather/visibilitylayerlist.h" #include "blackmisc/weather/windlayerlist.h" +#include "blackmisc/pq/pressure.h" namespace BlackMisc { @@ -38,7 +39,8 @@ namespace BlackMisc IndexPosition, IndexCloudLayers, IndexTemperatureLayers, - IndexWindLayers + IndexWindLayers, + IndexSurfacePressure }; //! Default constructor. @@ -54,7 +56,8 @@ namespace BlackMisc const CCloudLayerList &cloudLayers, const CTemperatureLayerList &temperatureLayers, const CVisibilityLayerList &visibilityLayers, - const CWindLayerList &windLayers); + const CWindLayerList &windLayers, + const PhysicalQuantities::CPressure &surfacePressure); //! Set identifier void setIdentifier(const QString &identifier) { m_identifier = identifier; } @@ -95,6 +98,12 @@ namespace BlackMisc //! Copies all weather data from other without modifying identifier and position. void copyWeatherDataFrom(const CGridPoint &other); + //! Set surface pressure + void setSurfacePressure(const PhysicalQuantities::CPressure &pressure) { m_surfacePressure = pressure; } + + //! Get surface pressure + PhysicalQuantities::CPressure getSurfacePressure() const { return m_surfacePressure; } + //! \copydoc BlackMisc::Mixin::Index::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -112,6 +121,7 @@ namespace BlackMisc CTemperatureLayerList m_temperatureLayers; CVisibilityLayerList m_visibilityLayers; CWindLayerList m_windLayers; + PhysicalQuantities::CPressure m_surfacePressure = { 1013.25, PhysicalQuantities::CPressureUnit::hPa() }; BLACK_METACLASS( CGridPoint, @@ -120,7 +130,8 @@ namespace BlackMisc BLACK_METAMEMBER(cloudLayers), BLACK_METAMEMBER(temperatureLayers), BLACK_METAMEMBER(visibilityLayers), - BLACK_METAMEMBER(windLayers) + BLACK_METAMEMBER(windLayers), + BLACK_METAMEMBER(surfacePressure) ); }; } // namespace diff --git a/src/blackmisc/weather/weathergrid.cpp b/src/blackmisc/weather/weathergrid.cpp index 933cefec5..81bfc76ec 100644 --- a/src/blackmisc/weather/weathergrid.cpp +++ b/src/blackmisc/weather/weathergrid.cpp @@ -72,7 +72,8 @@ namespace BlackMisc CCloudLayerList { cloudLayer }, CTemperatureLayerList { temperatureLayer }, CVisibilityLayerList { visibilityLayer } , - CWindLayerList { windLayer } + CWindLayerList { windLayer }, + { 1013.25, PhysicalQuantities::CPressureUnit::hPa() } }; static const CWeatherGrid weatherGrid = { gridPointGLOB }; @@ -123,7 +124,8 @@ namespace BlackMisc CCloudLayerList { cloudLayer1, cloudLayer2 }, CTemperatureLayerList { temperatureLayer }, CVisibilityLayerList { visibilityLayer }, - CWindLayerList { windLayer1, windLayer2 } + CWindLayerList { windLayer1, windLayer2 }, + { 1013.25, PhysicalQuantities::CPressureUnit::hPa() } }; static const CWeatherGrid weatherGrid({ gridPointGLOB }); diff --git a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp index 13f03ca12..78b759c07 100644 --- a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp +++ b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp @@ -245,6 +245,11 @@ namespace BlackWxPlugin for (const GfsGridPoint &gfsGridPoint : m_gfsWeatherGrid) { CTemperatureLayerList temperatureLayers; + + CAltitude surfaceAltitude (0, CAltitude::AboveGround, CLengthUnit::defaultUnit()); + CTemperatureLayer surfaceTemperature(surfaceAltitude, CTemperature(gfsGridPoint.surfaceTemperature, CTemperatureUnit::K()), {}, {}); + temperatureLayers.insert(surfaceTemperature); + CWindLayerList windLayers; for (auto isobaricLayerIt = gfsGridPoint.isobaricLayers.begin(); isobaricLayerIt != gfsGridPoint.isobaricLayers.end(); ++isobaricLayerIt) { @@ -283,10 +288,12 @@ namespace BlackWxPlugin cloudLayers.insert(cloudLayer); } + auto surfacePressure = PhysicalQuantities::CPressure { gfsGridPoint.surfacePressure, PhysicalQuantities::CPressureUnit::Pa() }; + CLatitude latitude(gfsGridPoint.latitude, CAngleUnit::deg()); CLongitude longitude(gfsGridPoint.longitude, CAngleUnit::deg()); auto position = CCoordinateGeodetic { latitude, longitude, {0} }; - BlackMisc::Weather::CGridPoint gridPoint(position, cloudLayers, temperatureLayers, {}, windLayers); + BlackMisc::Weather::CGridPoint gridPoint({}, position, cloudLayers, temperatureLayers, {}, windLayers, surfacePressure); m_weatherGrid.insert(gridPoint); } } @@ -467,8 +474,10 @@ namespace BlackWxPlugin return; } + // http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-0.shtml g2int parameterCategory = gfld->ipdtmpl[0]; g2int parameterNumber = gfld->ipdtmpl[1]; + g2int typeFirstFixedSurface = gfld->ipdtmpl[9]; g2int valueFirstFixedSurface = gfld->ipdtmpl[11]; std::array key { { parameterCategory, parameterNumber } }; @@ -479,9 +488,21 @@ namespace BlackWxPlugin return; } - double level = std::round(millibarToLevel(valueFirstFixedSurface)); - auto parameterValue = m_grib2ParameterTable[key]; + double level = 0; + switch (typeFirstFixedSurface) + { + case GroundOrWaterSurface: + level = 0; + break; + case IsobaricSurface: + level = std::round(millibarToLevel(valueFirstFixedSurface)); + break; + default: + CLogMessage(this).warning("Unexpected first fixed surface type: %1") << typeFirstFixedSurface; + return; + } + auto parameterValue = m_grib2ParameterTable[key]; switch (parameterValue.code) { case TMP: @@ -499,6 +520,7 @@ namespace BlackWxPlugin case PRMSL: break; case PRES: + setCloudPressure(gfld->fld, level); break; default: Q_ASSERT(false); @@ -563,7 +585,8 @@ namespace BlackWxPlugin { for (auto gridPointIt = m_gfsWeatherGrid.begin(); gridPointIt < m_gfsWeatherGrid.end(); ++gridPointIt) { - gridPointIt->isobaricLayers[level].temperature = fld[gridPointIt->fieldPosition]; + if (level > 0) { gridPointIt->isobaricLayers[level].temperature = fld[gridPointIt->fieldPosition]; } + else { gridPointIt->surfaceTemperature = fld[gridPointIt->fieldPosition]; } } } @@ -623,6 +646,15 @@ namespace BlackWxPlugin } } + void CWeatherDataGfs::setCloudPressure(const g2float *fld, double level) + { + for (auto gridPointIt = m_gfsWeatherGrid.begin(); gridPointIt < m_gfsWeatherGrid.end(); ++gridPointIt) + { + if (level > 0) { /* todo */ } + else { gridPointIt->surfacePressure = fld[gridPointIt->fieldPosition]; } + } + } + void CWeatherDataGfs::setSurfaceRain(const g2float *fld) { for (auto gridPointIt = m_gfsWeatherGrid.begin(); gridPointIt < m_gfsWeatherGrid.end(); ++gridPointIt) diff --git a/src/plugins/weatherdata/gfs/weatherdatagfs.h b/src/plugins/weatherdata/gfs/weatherdatagfs.h index 8174bbb44..b8af21fae 100644 --- a/src/plugins/weatherdata/gfs/weatherdatagfs.h +++ b/src/plugins/weatherdata/gfs/weatherdatagfs.h @@ -78,6 +78,7 @@ namespace BlackWxPlugin enum Grib2FixedSurfaceTypes { + GroundOrWaterSurface = 1, IsobaricSurface = 100, LowCloudBottomLevel = 212, LowCloudTopLevel = 213, @@ -123,6 +124,8 @@ namespace BlackWxPlugin QHash isobaricLayers; double surfaceRainRate = 0; double surfaceSnowRate = 0; + double surfacePressure = 0; + double surfaceTemperature = 0; }; QUrl getDownloadUrl() const; @@ -138,6 +141,7 @@ namespace BlackWxPlugin void setWindU(const g2float *fld, double level); void setCloudCoverage(const g2float *fld, int level); void setCloudLevel(const g2float *fld, int surfaceType, int level); + void setCloudPressure(const g2float *fld, double level); void setSurfaceRain(const g2float *fld); void setSurfaceSnow(const g2float *fld);