diff --git a/dbMeteoPoints/dbAggregationsHandler.cpp b/dbMeteoPoints/dbAggregationsHandler.cpp index 3d0324919..174000167 100644 --- a/dbMeteoPoints/dbAggregationsHandler.cpp +++ b/dbMeteoPoints/dbAggregationsHandler.cpp @@ -37,20 +37,21 @@ Crit3DAggregationsDbHandler::~Crit3DAggregationsDbHandler() } -bool Crit3DAggregationsDbHandler::saveAggregationData(int nZones, QString aggrType, QString periodType, QDate startDate, QDate endDate, meteoVariable variable, - std::vector< std::vector > aggregatedValues) +bool Crit3DAggregationsDbHandler::saveAggregationData(const std::vector &idZoneVector, const QString &aggrType, + const QString &periodType, const QDate &startDate, + const QDate &endDate, meteoVariable variable, + const std::vector > &aggregatedValues) { - initAggregatedTables(nZones, aggrType, periodType, startDate, endDate, variable); + initAggregatedTables(idZoneVector, aggrType, periodType, startDate, endDate, variable); createTmpAggrTable(); int idVariable = getIdfromMeteoVar(variable); long nrDays = long(startDate.daysTo(endDate)) + 1; QSqlQuery qry(_db); - // LC warning: the zones start from 1 - for (unsigned int zone = 1; zone <= unsigned(nZones); zone++) + for (unsigned int i = 0; i < idZoneVector.size(); i++) { - QString queryString = QString("REPLACE INTO `%1_%2_%3` VALUES").arg(QString::number(zone), aggrType, periodType); + QString queryString = QString("REPLACE INTO `%1_%2_%3` VALUES").arg(QString::number(idZoneVector[i]), aggrType, periodType); if (periodType == "H") { @@ -60,9 +61,9 @@ bool Crit3DAggregationsDbHandler::saveAggregationData(int nZones, QString aggrTy for (int hour = 0; hour < 24; hour++) { QString valueString = "NULL"; - if (! isEqual(aggregatedValues[day*24 + hour][zone-1], NODATA)) + if (! isEqual(aggregatedValues[day*24 + hour][i], NODATA)) { - valueString = QString::number(double(aggregatedValues[day*24 + hour][zone-1]), 'f', 1); + valueString = QString::number(double(aggregatedValues[day*24 + hour][i]), 'f', 1); } // the data refers to the past hour @@ -91,9 +92,9 @@ bool Crit3DAggregationsDbHandler::saveAggregationData(int nZones, QString aggrTy for (unsigned int day = 0; day < unsigned(nrDays); day++) { QString valueString = "NULL"; - if (! isEqual(aggregatedValues[day][zone-1], NODATA)) + if (! isEqual(aggregatedValues[day][i], NODATA)) { - valueString = QString::number(double(aggregatedValues[day][zone-1]), 'f', 1); + valueString = QString::number(double(aggregatedValues[day][i]), 'f', 1); } QString dateString = startDate.addDays(day).toString("yyyy-MM-dd"); @@ -213,14 +214,14 @@ bool Crit3DAggregationsDbHandler::getAggregationZonesReference(QString name, QSt } -void Crit3DAggregationsDbHandler::initAggregatedTables(int numZones, QString aggrType, QString periodType, QDate startDate, QDate endDate, meteoVariable variable) +void Crit3DAggregationsDbHandler::initAggregatedTables(const std::vector &idZoneVector, const QString &aggrType, const QString &periodType, const QDate &startDate, const QDate &endDate, meteoVariable variable) { int idVariable = getIdfromMeteoVar(variable); - for (int i = 1; i <= numZones; i++) + for (int i = 0; i < idZoneVector.size(); i++) { QString statement = QString("CREATE TABLE IF NOT EXISTS `%1_%2_%3` " "(date_time TEXT, id_variable INTEGER, value REAL, PRIMARY KEY(date_time,id_variable))") - .arg(i).arg(aggrType, periodType); + .arg(idZoneVector[i]).arg(aggrType, periodType); QSqlQuery qry(statement, _db); if(! qry.exec() ) @@ -230,7 +231,7 @@ void Crit3DAggregationsDbHandler::initAggregatedTables(int numZones, QString agg statement = QString("DELETE FROM `%1_%2_%3` WHERE date_time >= DATE('%4') " "AND date_time < DATE('%5', '+1 day') AND id_variable = %6") - .arg(i).arg(aggrType, periodType, startDate.toString("yyyy-MM-dd"), endDate.toString("yyyy-MM-dd")).arg(idVariable); + .arg(idZoneVector[i]).arg(aggrType, periodType, startDate.toString("yyyy-MM-dd"), endDate.toString("yyyy-MM-dd")).arg(idVariable); qry = QSqlQuery(statement, _db); if(! qry.exec() ) @@ -253,8 +254,8 @@ bool Crit3DAggregationsDbHandler::existIdPoint(const QString& idPoint) } -bool Crit3DAggregationsDbHandler::writeAggregationPointProperties(int nrPoints, QString aggrType, - std::vector lonVector, std::vector latVector) +bool Crit3DAggregationsDbHandler::writeAggregationPointProperties(const QString &aggrType, const std::vector &idZoneVector, + const std::vector &lonVector, const std::vector &latVector) { if (! _db.tables().contains(QLatin1String("point_properties")) ) { @@ -262,9 +263,9 @@ bool Crit3DAggregationsDbHandler::writeAggregationPointProperties(int nrPoints, } QSqlQuery qry(_db); - for (int i = 1; i <= nrPoints; i++) + for (int i = 0; i < idZoneVector.size(); i++) { - QString id = QString::number(i) + "_" + aggrType; + QString id = QString::number(idZoneVector[i]) + "_" + aggrType; QString name = id; if (! existIdPoint(id)) @@ -274,8 +275,8 @@ bool Crit3DAggregationsDbHandler::writeAggregationPointProperties(int nrPoints, qry.bindValue(":id_point", id); qry.bindValue(":name", name); - qry.bindValue(":latitude", latVector[i-1]); - qry.bindValue(":longitude", lonVector[i-1]); + qry.bindValue(":latitude", latVector[i]); + qry.bindValue(":longitude", lonVector[i]); qry.bindValue(":altitude", 0); qry.bindValue(":is_active", 1); diff --git a/dbMeteoPoints/dbAggregationsHandler.h b/dbMeteoPoints/dbAggregationsHandler.h index cc8e944bc..634ba7d14 100644 --- a/dbMeteoPoints/dbAggregationsHandler.h +++ b/dbMeteoPoints/dbAggregationsHandler.h @@ -30,12 +30,15 @@ bool existIdPoint(const QString& idPoint); bool writeAggregationZonesTable(QString name, QString filename, QString field); bool getAggregationZonesReference(QString name, QString* filename, QString* field); - void initAggregatedTables(int numZones, QString aggrType, QString periodType, QDate startDate, QDate endDate, meteoVariable variable); + void initAggregatedTables(const std::vector &idZoneVector, const QString &aggrType, const QString &periodType, + const QDate &startDate, const QDate &endDate, meteoVariable variable); - bool writeAggregationPointProperties(int nrPoints, QString aggrType, std::vector lonVector, std::vector latVector); + bool writeAggregationPointProperties(const QString &aggrType, const std::vector &idZoneVector, + const std::vector &lonVector, const std::vector &latVector); - bool saveAggregationData(int nZones, QString aggrType, QString periodType, QDate startDate, QDate endDate, - meteoVariable variable, std::vector< std::vector > aggregatedValues); + bool saveAggregationData(const std::vector &idZoneVector, const QString &aggrType, + const QString &periodType, const QDate &startDate, const QDate &endDate, + meteoVariable variable, const std::vector> &aggregatedValues); bool insertTmpAggr(QDate startDate, QDate endDate, meteoVariable variable, std::vector< std::vector > aggregatedValues, int nZones); bool saveTmpAggrData(QString aggrType, QString periodType, int nZones); diff --git a/gis/color.cpp b/gis/color.cpp index c4cd4d256..0ecd49415 100644 --- a/gis/color.cpp +++ b/gis/color.cpp @@ -97,9 +97,6 @@ bool Crit3DColorScale::classify() nrIntervals = MAXVALUE(_nrKeyColors -1, 1); nrStep = _nrColors / nrIntervals; - _nrColors = nrStep * nrIntervals; - color.resize(_nrColors); - for (i = 0; i < nrIntervals; i++) { dRed = float(keyColor[i+1].red - keyColor[i].red) / float(nrStep); @@ -114,7 +111,13 @@ bool Crit3DColorScale::classify() color[n].blue = keyColor[i].blue + short(dBlue * float(j)); } } - color[_nrColors-1] = keyColor[_nrKeyColors -1]; + + // last colors + int lastIndex = nrStep * nrIntervals; + for (i = lastIndex; i < _nrColors; i++) + { + color[i] = keyColor[_nrKeyColors -1]; + } } return true; diff --git a/graphics/colorLegend.cpp b/graphics/colorLegend.cpp index d999466f8..2941e4860 100644 --- a/graphics/colorLegend.cpp +++ b/graphics/colorLegend.cpp @@ -40,13 +40,13 @@ void ColorLegend::paintEvent(QPaintEvent *event) int legendWidth = painter.window().width() - BLANK_DX*2; unsigned int nrStep = this->colorScale->nrColors(); - unsigned int nrStepText = MAXVALUE(nrStep / 4, 1); + unsigned int nrStepText = MAXVALUE(round(float(nrStep) / 4.f), 1); double dx = double(legendWidth) / double(nrStep+1); double value = this->colorScale->minimum(); double step = (colorScale->maximum() - colorScale->minimum()) / double(nrStep); - double stepText = (colorScale->maximum() - colorScale->minimum()) / double(nrStepText); + double range = (colorScale->maximum() - colorScale->minimum()); QString valueStr; int nrDigits; @@ -71,7 +71,7 @@ void ColorLegend::paintEvent(QPaintEvent *event) if (value < 0) nrDigits++; double decimal = fabs(value - round(value)); - if ((decimal / stepText) > 1) + if ((decimal / range) > 0.1) { // two decimals valueStr = QString::number(value, 'f', 2); @@ -79,7 +79,7 @@ void ColorLegend::paintEvent(QPaintEvent *event) } else { - if ((decimal / stepText) > 0.1) + if ((decimal / range) > 0.01) { // one decimal valueStr = QString::number(value, 'f', 1); diff --git a/pragaProject/pragaProject.cpp b/pragaProject/pragaProject.cpp index 17e3b46fb..15d56e4e7 100644 --- a/pragaProject/pragaProject.cpp +++ b/pragaProject/pragaProject.cpp @@ -1824,12 +1824,11 @@ bool PragaProject::averageSeriesOnZonesMeteoGrid(meteoVariable variable, meteoCo std::vector > indexRowCol(meteoGridDbHandler->gridStructure().header().nrRows, std::vector(meteoGridDbHandler->gridStructure().header().nrCols, NODATA)); gis::updateMinMaxRasterGrid(zoneGrid); - - std::vector > zoneValues((unsigned int)(zoneGrid->maximum), std::vector()); + int maximumIdZone = int(zoneGrid->maximum); std::vector utmXvector, utmYvector; std::vector count; - for (int i = 0; i < int(zoneGrid->maximum); i++) + for (int i = 0; i <= maximumIdZone; i++) { utmXvector.push_back(0); utmYvector.push_back(0); @@ -1848,32 +1847,38 @@ bool PragaProject::averageSeriesOnZonesMeteoGrid(meteoVariable variable, meteoCo { unsigned zoneIndex = unsigned(zoneGridValue); - if (zoneIndex > 0 && zoneIndex <= zoneGrid->maximum) + if (zoneIndex >= 0 && zoneIndex <= zoneGrid->maximum) { - utmXvector[zoneIndex-1] += utmx; - utmYvector[zoneIndex-1] += utmy; - count[zoneIndex-1]++; + utmXvector[zoneIndex] += utmx; + utmYvector[zoneIndex] += utmy; + count[zoneIndex]++; } } } } + // define the center position of valid zones + std::vector idZoneVector; std::vector latVector, lonVector; - for (unsigned int zonePos = 0; zonePos < zoneValues.size(); zonePos++) + for (unsigned int i = 0; i < count.size(); i++) { - // average x, y - utmXvector[zonePos] /= count[zonePos]; - utmYvector[zonePos] /= count[zonePos]; + if (count[i] > 0) + { + idZoneVector.push_back(i); + + // average x, y + utmXvector[i] /= count[i]; + utmYvector[i] /= count[i]; - double lat, lon; - gis::getLatLonFromUtm(gisSettings, utmXvector[zonePos], utmYvector[zonePos], &lat, &lon); - latVector.push_back(lat); - lonVector.push_back(lon); + double lat, lon; + gis::getLatLonFromUtm(gisSettings, utmXvector[i], utmYvector[i], &lat, &lon); + latVector.push_back(lat); + lonVector.push_back(lon); + } } - // save point properties - int nrAggregationPoints = int(zoneValues.size()); - if (! aggregationDbHandler->writeAggregationPointProperties(nrAggregationPoints, aggregationString, lonVector, latVector)) + // save point properties (center points) + if (! aggregationDbHandler->writeAggregationPointProperties(aggregationString, idZoneVector, lonVector, latVector)) { errorString = aggregationDbHandler->error(); return false; @@ -1935,19 +1940,19 @@ bool PragaProject::averageSeriesOnZonesMeteoGrid(meteoVariable variable, meteoCo if (getVarFrequency(variable) == hourly) { - return hourlyZoneAggregationMeteoGrid(variable, aggregationString, threshold, zoneGrid, zoneValues, outputSeries, + return hourlyZoneAggregationMeteoGrid(variable, aggregationString, threshold, zoneGrid, idZoneVector, outputSeries, indexRowCol, meteoGridRow, meteoGridCol, valuesFirstDate, nrDays, showInfo); } else { - return dailyZoneAggregationMeteoGrid(variable, aggregationString, threshold, zoneGrid, zoneValues, outputSeries, + return dailyZoneAggregationMeteoGrid(variable, aggregationString, threshold, zoneGrid, idZoneVector, outputSeries, indexRowCol, meteoGridRow, meteoGridCol, valuesFirstDate, nrDays, showInfo); } } bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const QString& aggregationString, float threshold, - gis::Crit3DRasterGrid* zoneGrid, std::vector> &zoneValues, + gis::Crit3DRasterGrid* zoneGrid, std::vector &idZoneVector, std::vector &outputSeries, std::vector> &indexRowCol, std::vector> &meteoGridRow, std::vector> &meteoGridCol, const Crit3DDate& startDate, int nrDays, bool showInfo) @@ -1958,8 +1963,12 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q infoStep = setProgressBar("Computing spatial aggregation...", nrDays); } + // matrix of values + unsigned int nrOfZones = unsigned(idZoneVector.size()); + std::vector> zoneValues(nrOfZones, std::vector()); + aggregationMethod spatialElab = getAggregationMethod(aggregationString.toStdString()); - std::vector> dailyElabAggregation(nrDays, std::vector(int(zoneGrid->maximum), NODATA)); + std::vector> dailyElabAggregation(nrDays, std::vector(nrOfZones, NODATA)); for (int day = 0; day < nrDays; day++) { @@ -1973,14 +1982,6 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q float zoneNr = zoneGrid->value[zoneRow][zoneCol]; if (! isEqual(zoneNr, zoneGrid->header->flag)) { - unsigned zoneIndex = unsigned(zoneNr); - if (zoneIndex < 1 || zoneIndex > zoneGrid->maximum) - { - errorString = "Invalid zone number: " + QString::number(zoneIndex); - errorString += "\nZone number has to be between 1 and " + QString::number(zoneGrid->maximum); - return false; - } - if (meteoGridRow[zoneRow][zoneCol] != NODATA && meteoGridCol[zoneRow][zoneCol] != NODATA) { int indexSeries = indexRowCol[meteoGridRow[zoneRow][zoneCol]][meteoGridCol[zoneRow][zoneCol]]; @@ -1989,7 +1990,14 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q float value = outputSeries.at(indexSeries * nrDays + day); if (value != meteoGridDbHandler->gridStructure().header().flag) { - zoneValues[zoneIndex-1].push_back(value); + const auto it = std::find(idZoneVector.begin(), idZoneVector.end(), int(zoneNr)); + if (it == idZoneVector.end()) + { + errorString = "Invalid zone number: " + QString::number(zoneNr); + return false; + } + int index = std::distance(idZoneVector.begin(), it); + zoneValues[index].push_back(value); } } } @@ -1997,10 +2005,9 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q } } - for (unsigned int zoneIndex = 0; zoneIndex < zoneValues.size(); zoneIndex++) + for (unsigned int i = 0; i < nrOfZones; i++) { - std::vector validValues; - validValues = zoneValues[zoneIndex]; + std::vector validValues = zoneValues[i]; if (! isEqual(threshold, NODATA)) { extractValidValuesWithThreshold(validValues, threshold); @@ -2039,14 +2046,15 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q } } - dailyElabAggregation[unsigned(day)][zoneIndex] = res; + dailyElabAggregation[unsigned(day)][i] = res; } - // clear zoneValues vectors - for (unsigned int zoneIndex = 0; zoneIndex < zoneValues.size(); zoneIndex++) + // clear zoneValues matrix + for (unsigned int i = 0; i < nrOfZones; i++) { - zoneValues[zoneIndex].clear(); + zoneValues[i].clear(); } + // end DAY } if (showInfo) @@ -2058,8 +2066,10 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q // save aggregation into DB QDate startQDate = getQDate(startDate); QDate endQDate = startQDate.addDays(nrDays-1); - bool isOk = aggregationDbHandler->saveAggregationData(int(zoneGrid->maximum), aggregationString, "D", + bool isOk = aggregationDbHandler->saveAggregationData(idZoneVector, aggregationString, "D", startQDate, endQDate, variable, dailyElabAggregation); + dailyElabAggregation.clear(); + if (! isOk) { errorString = aggregationDbHandler->error(); @@ -2072,7 +2082,7 @@ bool PragaProject::dailyZoneAggregationMeteoGrid(meteoVariable variable, const Q bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const QString& aggregationString, float threshold, - gis::Crit3DRasterGrid* zoneRaster, std::vector> &zoneValues, + gis::Crit3DRasterGrid* zoneRaster, std::vector &idZoneVector, std::vector &outputSeries, std::vector> &indexRowCol, std::vector> &meteoGridRow, std::vector> &meteoGridCol, const Crit3DDate& startDate, int nrDays, bool showInfo) @@ -2083,8 +2093,12 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const infoStep = setProgressBar("Computing spatial aggregation...", nrDays); } + // matrix of values + unsigned int nrOfZones = unsigned(idZoneVector.size()); + std::vector> zoneValues(nrOfZones, std::vector()); + aggregationMethod spatialElab = getAggregationMethod(aggregationString.toStdString()); - std::vector> hourlyElabAggregation(nrDays * 24, std::vector(int(zoneRaster->maximum), NODATA)); + std::vector> hourlyElabAggregation(nrDays * 24, std::vector(nrOfZones, NODATA)); for (int day = 0; day < nrDays; day++) { @@ -2100,14 +2114,6 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const float zoneNr = zoneRaster->value[row][col]; if (! isEqual(zoneNr, zoneRaster->header->flag)) { - unsigned zoneIndex = unsigned(zoneNr); - if (zoneIndex < 1 || zoneIndex > zoneRaster->maximum) - { - errorString = "Invalid zone number: " + QString::number(zoneIndex); - errorString += "\nZone number has to be between 1 and " + QString::number(zoneRaster->maximum); - return false; - } - if (meteoGridRow[row][col] != NODATA && meteoGridCol[row][col] != NODATA) { int indexSeries = indexRowCol[meteoGridRow[row][col]][meteoGridCol[row][col]]; @@ -2116,7 +2122,14 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const float value = outputSeries.at(indexSeries * nrDays * 24 + (day * 24) + hour); if (value != meteoGridDbHandler->gridStructure().header().flag) { - zoneValues[zoneIndex-1].push_back(value); + const auto it = std::find(idZoneVector.begin(), idZoneVector.end(), int(zoneNr)); + if (it == idZoneVector.end()) + { + errorString = "Invalid zone number: " + QString::number(zoneNr); + return false; + } + int index = std::distance(idZoneVector.begin(), it); + zoneValues[index].push_back(value); } } } @@ -2124,10 +2137,10 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const } } - for (unsigned int zoneIndex = 0; zoneIndex < zoneValues.size(); zoneIndex++) + for (unsigned int i = 0; i < nrOfZones; i++) { std::vector validValues; - validValues = zoneValues[zoneIndex]; + validValues = zoneValues[i]; if (! isEqual(threshold, NODATA)) { extractValidValuesWithThreshold(validValues, threshold); @@ -2166,20 +2179,19 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const } } - hourlyElabAggregation[unsigned(day * 24 + hour)][zoneIndex] = res; + hourlyElabAggregation[unsigned(day * 24 + hour)][i] = res; } // clear zoneValues vectors - for (unsigned int zoneIndex = 0; zoneIndex < zoneValues.size(); zoneIndex++) + for (unsigned int i = 0; i < nrOfZones; i++) { - zoneValues[zoneIndex].clear(); + zoneValues[i].clear(); } // end hour } // end day } - if (showInfo) { closeProgressBar(); @@ -2189,14 +2201,17 @@ bool PragaProject::hourlyZoneAggregationMeteoGrid(meteoVariable variable, const // save aggregation into DB QDate startQDate = getQDate(startDate); QDate endQDate = startQDate.addDays(nrDays-1); - bool isOk = aggregationDbHandler->saveAggregationData(int(zoneRaster->maximum), aggregationString, "H", - startQDate, endQDate, variable, hourlyElabAggregation); + bool isOk = aggregationDbHandler->saveAggregationData(idZoneVector, aggregationString, "H", + startQDate, endQDate, variable, hourlyElabAggregation); + hourlyElabAggregation.clear(); + if (! isOk) { errorString = aggregationDbHandler->error(); } - if (showInfo) closeProgressBar(); + if (showInfo) + closeProgressBar(); return isOk; } diff --git a/pragaProject/pragaProject.h b/pragaProject/pragaProject.h index 790dd3dff..69a3021ad 100644 --- a/pragaProject/pragaProject.h +++ b/pragaProject/pragaProject.h @@ -165,13 +165,13 @@ bool saveLogProceduresGrid(QString nameProc, QDate date); bool dailyZoneAggregationMeteoGrid(meteoVariable variable, const QString& aggregationString, float threshold, - gis::Crit3DRasterGrid* zoneGrid, std::vector> &zoneValues, std::vector &outputSeries, + gis::Crit3DRasterGrid* zoneGrid, std::vector &idZoneVector, std::vector &outputSeries, std::vector> &indexRowCol, std::vector> &meteoGridRow, std::vector> &meteoGridcol, const Crit3DDate& startDate, int nrDays, bool showInfo); bool hourlyZoneAggregationMeteoGrid(meteoVariable variable, const QString& aggregationString, float threshold, - gis::Crit3DRasterGrid* zoneRaster, std::vector> &zoneValues, std::vector &outputSeries, + gis::Crit3DRasterGrid* zoneRaster, std::vector &idZoneVector, std::vector &outputSeries, std::vector> &indexRowCol, std::vector> &meteoGridRow, std::vector> &meteoGridcol, const Crit3DDate& startDate, int nrDays, bool showInfo);