diff --git a/DOC/CRITERIA1D_article.pdf b/DOC/CRITERIA1D_article.pdf new file mode 100644 index 00000000..19390f66 Binary files /dev/null and b/DOC/CRITERIA1D_article.pdf differ diff --git a/agrolib/commonDialogs/formSelection.cpp b/agrolib/commonDialogs/formSelection.cpp index 4b53857f..e382835e 100644 --- a/agrolib/commonDialogs/formSelection.cpp +++ b/agrolib/commonDialogs/formSelection.cpp @@ -7,7 +7,7 @@ FormSelection::FormSelection(QList stringList_, QString title) this->setWindowTitle(title); QVBoxLayout* mainLayout = new QVBoxLayout; - this->resize(250, 100); + this->resize(300, 100); QHBoxLayout *layoutOk = new QHBoxLayout; QHBoxLayout *datasetLayout = new QHBoxLayout; diff --git a/agrolib/crop/landUnit.cpp b/agrolib/crop/landUnit.cpp index d39f754d..2eb7f471 100644 --- a/agrolib/crop/landUnit.cpp +++ b/agrolib/crop/landUnit.cpp @@ -11,6 +11,7 @@ Crit3DLandUnit::Crit3DLandUnit() description = "Default land use"; idCrop = "FALLOW"; idLandUse = "FALLOW"; + landUseType = LANDUSE_FALLOW; roughness = 0.05; pond = 0.002; @@ -48,7 +49,17 @@ bool loadLandUnitList(const QSqlDatabase &dbCrop, std::vector &l landUnitList[i].name = query.value("name").toString(); landUnitList[i].description = query.value("description").toString(); landUnitList[i].idCrop = query.value("id_crop").toString(); - landUnitList[i].idLandUse = query.value("id_landuse").toString(); + landUnitList[i].idLandUse = query.value("id_landuse").toString().toUpper(); + + try + { + landUnitList[i].landUseType = MapLandUseFromString.at(landUnitList[i].idLandUse.toStdString()); + } + catch (const std::out_of_range& outOfErrorStr) + { + errorStr = QString("%1 is not a valid landUse type" ).arg(landUnitList[i].idLandUse); + landUnitList[i].landUseType = LANDUSE_FALLOW; + } landUnitList[i].roughness = query.value("roughness").toDouble(); landUnitList[i].pond = query.value("pond").toDouble(); diff --git a/agrolib/crop/landUnit.h b/agrolib/crop/landUnit.h index fb11f46c..c380b55d 100644 --- a/agrolib/crop/landUnit.h +++ b/agrolib/crop/landUnit.h @@ -3,8 +3,26 @@ #include #include + #include + class QSqlDatabase; + enum landUseTypeList {LANDUSE_BARESOIL, LANDUSE_FALLOW, LANDUSE_HERBACEOUS, LANDUSE_HORTICULTURAL, LANDUSE_GRASS, + LANDUSE_ORCHARD, LANDUSE_FOREST, LANDUSE_URBAN, LANDUSE_ROAD, LANDUSE_WATERBODIES }; + + const std::map MapLandUseFromString = { + { "BARE", LANDUSE_BARESOIL }, + { "FALLOW", LANDUSE_FALLOW }, + { "HERBACEOUS", LANDUSE_HERBACEOUS }, + { "HORTI", LANDUSE_HORTICULTURAL }, + { "GRASS", LANDUSE_GRASS }, + { "ORCHARD", LANDUSE_ORCHARD }, + { "FOREST", LANDUSE_FOREST }, + { "URBAN", LANDUSE_URBAN }, + { "ROAD", LANDUSE_ROAD }, + { "WATER", LANDUSE_WATERBODIES }, + }; + class Crit3DLandUnit { public: @@ -14,6 +32,7 @@ QString description; QString idCrop; QString idLandUse; + int landUseType; double roughness; // Gauckler–Manning roughness coefficient [s m-1/3] double pond; // surface pond (immobilized water) [m] diff --git a/agrolib/dbMeteoPoints/download.cpp b/agrolib/dbMeteoPoints/download.cpp index e1f03aee..88a99096 100644 --- a/agrolib/dbMeteoPoints/download.cpp +++ b/agrolib/dbMeteoPoints/download.cpp @@ -503,14 +503,18 @@ bool Download::downloadDailyData(const QDate &startDate, const QDate &endDate, c if (idPoint != "" && flag.left(1) != "1" && flag.left(3) != "054") { + value = NODATA; + if (flag.left(1) == "2") + value = fields[4].toDouble(); + else + value = fields[3].toDouble(); + idArkimet = fields[2].toInt(); if (idArkimet == PREC_ID) if ((prec0024 && fields[0].mid(8,2) != "00") || (!prec0024 && fields[0].mid(8,2) != "08")) continue; - value = fields[3].toDouble(); - // conversion from average daily radiation to integral radiation if (idArkimet == RAD_ID) { @@ -638,7 +642,7 @@ bool Download::downloadHourlyData(const QDate &startDate, const QDate &endDate, _dbMeteo->queryString = ""; QString line, dateTime, idPoint, flag, varName; - QString idVariable, value, frequency; + QString idVariable, value, secondValue, frequency; QList fields; int i, idVarArkimet; @@ -679,14 +683,20 @@ bool Download::downloadHourlyData(const QDate &startDate, const QDate &endDate, if (isVarOk && fields[3] != "") { value = fields[3]; + secondValue = fields[4]; // flag flag = fields[6]; - if (flag.left(1) != "1" && flag.left(3) != "054") + if (flag.left(1) != "1" && flag.left(1) != "2" && flag.left(3) != "054") { _dbMeteo->appendQueryHourly(dateTime, idPoint, idVariable, value, isFirstData); isFirstData = false; } + else if(flag.left(1) == "2") + { + _dbMeteo->appendQueryHourly(dateTime, idPoint, idVariable, secondValue, isFirstData); + isFirstData = false; + } } } } diff --git a/agrolib/gis/gis.cpp b/agrolib/gis/gis.cpp index d57ae5b9..ab307ada 100644 --- a/agrolib/gis/gis.cpp +++ b/agrolib/gis/gis.cpp @@ -1520,7 +1520,7 @@ namespace gis double resampleFactor = newGrid->header->cellSize / oldGrid.header->cellSize; - int row, col, tmpRow, tmpCol, nrValues, maxValues; + int row, col, tmpRow, tmpCol, nrValues; gis::Crit3DPoint myLL, myUR; std::vector values; @@ -1529,9 +1529,10 @@ namespace gis for (row = 0; row < newGrid->header->nrRows; row++) for (col = 0; col < newGrid->header->nrCols; col++) { + // initialize newGrid->value[row][col] = newGrid->header->flag; - float value = NODATA; + if (resampleFactor <= 1. || elab == aggrCenter) { double x, y; @@ -1539,52 +1540,58 @@ namespace gis oldGrid.getRowCol(x, y, tmpRow, tmpCol); if (! gis::isOutOfGridRowCol(tmpRow, tmpCol, oldGrid)) { - value = oldGrid.value[tmpRow][tmpCol]; + float tmpValue = oldGrid.value[tmpRow][tmpCol]; + if (! isEqual(tmpValue, oldGrid.header->flag)) + value = tmpValue; } } else { - double step = oldGrid.header->cellSize * 0.5; + int nrStep = floor(resampleFactor) + 1; + double step = newGrid->header->cellSize / nrStep; + double halfStep = step * 0.5; double x0, y0; newGrid->getXY(row, col, x0, y0); - myLL.utm.x = x0 - (newGrid->header->cellSize / 2) + step; - myLL.utm.y = y0 - (newGrid->header->cellSize / 2) + step; - myUR.utm.x = x0 + (newGrid->header->cellSize / 2) - step; - myUR.utm.y = y0 + (newGrid->header->cellSize / 2) - step; + myLL.utm.x = x0 - (newGrid->header->cellSize / 2) + halfStep; + myLL.utm.y = y0 - (newGrid->header->cellSize / 2) + halfStep; + myUR.utm.x = x0 + (newGrid->header->cellSize / 2) - halfStep; + myUR.utm.y = y0 + (newGrid->header->cellSize / 2) - halfStep; values.clear(); - maxValues = 0; - - double x = myLL.utm.x; - while(x <= myUR.utm.x) + int maxNrValues = 0; + for (int i = 0; i < nrStep; i++) { - double y = myLL.utm.y; - while(y <= myUR.utm.y) + double x = myLL.utm.x + step * i; + for (int j = 0; j < nrStep; j++) { - maxValues++; + double y = myLL.utm.y + step * j; float tmpValue = gis::getValueFromXY(oldGrid, x, y); if (! isEqual(tmpValue, oldGrid.header->flag)) { values.push_back(tmpValue); } - - y += step; + maxNrValues++; } - x += step; } nrValues = int(values.size()); - if (maxValues > 0) + if (maxNrValues > 0) { - if ((float(nrValues) / float(maxValues)) > nodataRatioThreshold) + if ((float(nrValues) / float(maxNrValues)) > nodataRatioThreshold) { if (elab == aggrAverage) value = statistics::mean(values); else if (elab == aggrMedian) value = sorting::percentile(values, nrValues, 50, true); else if (elab == aggrPrevailing) - value = prevailingValue(values); + { + int nrMissing = maxNrValues - nrValues; + if (nrMissing < nrValues) + { + value = prevailingValue(values); + } + } } } } diff --git a/agrolib/interpolation/interpolation.cpp b/agrolib/interpolation/interpolation.cpp index fac93b01..f137a0dd 100644 --- a/agrolib/interpolation/interpolation.cpp +++ b/agrolib/interpolation/interpolation.cpp @@ -115,9 +115,67 @@ float getProxyMinValue(std::vector &myPoints, unsi return minValue; } -unsigned sortPointsByDistance(unsigned maxIndex, std::vector &myPoints, std::vector &myValidPoints) + +// return number of sorted valid points +unsigned sortPointsByDistance(unsigned maxNrPoints, std::vector &pointList, + std::vector &validPointList) +{ + if (pointList.empty()) + return 0; + + // initializes the distance list + std::vector distanceList; + for (unsigned i = 0; i < pointList.size(); i++) + { + if (! isEqual(pointList[i].distance, 0) && ! isEqual(pointList[i].distance, NODATA)) + { + distanceList.push_back(pointList[i].distance); + } + } + // check + if (distanceList.empty()) + return 0; + + // sorts the distances + std::sort(distanceList.begin(), distanceList.end()); + + // initializes the list of points used + std::vector isUsedPoint; + isUsedPoint.resize(pointList.size()); + for (unsigned i = 0; i < isUsedPoint.size(); i++) + { + isUsedPoint[i] = false; + } + + // saves the sorted points + validPointList.clear(); + for (unsigned i = 0; i < distanceList.size(); i++) + { + float currentDistance = distanceList[i]; + for (unsigned i = 0; i < pointList.size(); i++) + { + if (! isUsedPoint[i]) + { + if (isEqual(pointList[i].distance, currentDistance)) + { + validPointList.push_back(pointList[i]); + isUsedPoint[i] = true; + break; + } + } + } + if (validPointList.size() == maxNrPoints) + break; + } + + return validPointList.size(); +} + +/* + * old code +unsigned sortPointsByDistance(unsigned maxIndex, std::vector &points, std::vector &myValidPoints) { - if (myPoints.size() == 0) return 0; + if (points.size() == 0) return 0; unsigned i, first, index, outIndex; float min_value = NODATA; @@ -125,49 +183,55 @@ unsigned sortPointsByDistance(unsigned maxIndex, std::vector indice_minimo; indici_ordinati.resize(maxIndex); - indice_minimo.resize(myPoints.size()); + indice_minimo.resize(points.size()); first = 0; index = 0; - bool exit = false; + bool isExit = false; - while (index < maxIndex && !exit) + while (index < maxIndex && !isExit) { if (first == 0) { i = 0; - while ((! myPoints[i].isActive || (isEqual(myPoints[i].distance, 0))) && (i < myPoints.size()-1)) + while ((! points[i].isActive || (isEqual(points[i].distance, 0))) && (i < points.size()-1)) i++; - if (i == (myPoints.size()-1) && ! myPoints[i].isActive) - exit=true; + if (i == (points.size()-1) && ! points[i].isActive) + isExit = true; else { first = 1; indice_minimo[first-1] = i; - min_value = myPoints[i].distance; + min_value = points[i].distance; } } else - min_value = myPoints[unsigned(indice_minimo[first-1])].distance; + { + min_value = points[unsigned(indice_minimo[first-1])].distance; + } - if (!exit) + if (! isExit) { - for (i = unsigned(indice_minimo[first-1]) + 1; i < myPoints.size(); i++) - if (isEqual(min_value, NODATA) || myPoints[i].distance < min_value) - if (myPoints[i].isActive) - if (myPoints[i].distance > 0) + for (i = unsigned(indice_minimo[first-1]) + 1; i < points.size(); i++) + if (isEqual(min_value, NODATA) || points[i].distance < min_value) + if (points[i].isActive) + if (points[i].distance > 0) { first++; - min_value = myPoints[i].distance; + min_value = points[i].distance; indice_minimo[first-1] = i; } - indici_ordinati[index] = indice_minimo[first-1]; - myPoints[indice_minimo[first-1]].isActive = false; - index++; - first--; + int currentIndex = indice_minimo[first-1]; + if (! isEqual(points[currentIndex].distance, 0)) + { + indici_ordinati[index] = currentIndex; + points[currentIndex].isActive = false; + index++; + first--; + } } } @@ -176,14 +240,15 @@ unsigned sortPointsByDistance(unsigned maxIndex, std::vector &myPoints, Crit3DInterpolationSettings* mySettings, @@ -233,29 +298,29 @@ void computeDistances(meteoVariable myVar, vector bool neighbourhoodVariability(meteoVariable myVar, std::vector &myInterpolationPoints, Crit3DInterpolationSettings* mySettings, - float x, float y, float z, int nMax, + float x, float y, float z, int maxNrPoints, float* devSt, float* avgDeltaZ, float* minDistance) { - int i, max_points; + int i, nrValid; float* dataNeighborhood; float myValue; vector deltaZ; vector validPoints; computeDistances(myVar, myInterpolationPoints, mySettings, x, y, z, true); - max_points = sortPointsByDistance(nMax, myInterpolationPoints, validPoints); + nrValid = sortPointsByDistance(maxNrPoints, myInterpolationPoints, validPoints); - if (max_points > 1) + if (nrValid > 1) { - dataNeighborhood = (float *) calloc (max_points, sizeof(float)); + dataNeighborhood = (float *) calloc (nrValid, sizeof(float)); - for (i=0; iz != NODATA) { @@ -781,6 +846,7 @@ float computeShepardInitialRadius(float area, unsigned int allPointsNr, unsigned return float(sqrt((minPointsNr * area) / (float(PI) * allPointsNr))); } + float shepardSearchNeighbour(vector &inputPoints, Crit3DInterpolationSettings* settings, vector &outputPoints) @@ -930,12 +996,14 @@ float modifiedShepardIdw(vector &myPoints, else S[i] = 0; - weightSum = weightSum + S[i]; + weightSum += S[i]; } } if (weightSum == 0) + { return NODATA; + } // including direction for (unsigned int i=0; i < validPoints.size(); i++) @@ -998,6 +1066,7 @@ float inverseDistanceWeighted(vector &myPointList } /* + * wind? float gaussWeighted(vector &myPointList) { double sum, sumWeights, weight; @@ -1028,63 +1097,6 @@ float gaussWeighted(vector &myPointList) } */ -/*void localSelection_new(std::vector &inputPoints, std::vector &selectedPoints, - float x, float y, float z, Crit3DInterpolationSettings& mySettings) -{ - std::vector tempPoints; - unsigned int i; - float radius; - unsigned int nrValid = 0; - unsigned int minPoints = unsigned(mySettings.getMinPointsLocalDetrending() * 1.2); - float shepardInitialRadius = computeShepardInitialRadius(mySettings.getPointsBoundingBoxArea(), unsigned(inputPoints.size()), minPoints); - - // define a first neighborhood inside initial radius - for (i=0; i < inputPoints.size(); i++) - { - inputPoints[i].distance = gis::computeDistance(x, y, float((inputPoints[i]).point->utm.x), float((inputPoints[i]).point->utm.y)); - if (inputPoints[i].distance <= shepardInitialRadius && - inputPoints[i].distance > 0 && - checkLapseRateCode(inputPoints[i].lapseRateCode, mySettings.getUseLapseRateCode(), true)) - { - tempPoints.push_back(inputPoints[i]); - nrValid++; - } - } - - if (tempPoints.size() <= minPoints) - { - nrValid = sortPointsByDistance(minPoints + 1, inputPoints, selectedPoints); - if (nrValid > minPoints) - { - radius = selectedPoints[minPoints].distance; - selectedPoints.pop_back(); - } - else - radius = selectedPoints[nrValid-1].distance + float(EPSILON); - } - else if (tempPoints.size() > minPoints) - { - nrValid = sortPointsByDistance(minPoints + 1, tempPoints, selectedPoints); - radius = selectedPoints[minPoints].distance; - selectedPoints.pop_back(); - } - else - { - selectedPoints = tempPoints; - radius = shepardInitialRadius; - } - - for (int i = 0; i < selectedPoints.size(); i++) - { - selectedPoints[i].regressionWeight = MAXVALUE((-(1/std::pow(radius,4)*(std::pow(selectedPoints[i].distance,4)))+1),EPSILON); - //selectedPoints[i].regressionWeight = 1; - } - mySettings.setLocalRadius(float(radius)); - - return; -} -*/ - // TODO elevation std dev? void localSelection(vector &inputPoints, vector &selectedPoints, @@ -2384,8 +2396,10 @@ float interpolate(vector &myPoints, Crit3DInterpo } else myResult = 0; - if (int(myResult) == int(NODATA)) + if (isEqual(myResult, NODATA)) + { return NODATA; + } else if (!mySettings->getUseDoNotRetrend()) myResult += retrend(myVar, myProxyValues, mySettings); diff --git a/agrolib/interpolation/interpolation.h b/agrolib/interpolation/interpolation.h index 78a57291..63b51174 100644 --- a/agrolib/interpolation/interpolation.h +++ b/agrolib/interpolation/interpolation.h @@ -68,7 +68,7 @@ void clearInterpolationPoints(); bool checkPrecipitationZero(const std::vector &myPoints, float precThreshold, int &nrNotNull); - bool neighbourhoodVariability(meteoVariable myVar, std::vector &myInterpolationPoints, Crit3DInterpolationSettings *mySettings, float x, float y, float z, int nMax, + bool neighbourhoodVariability(meteoVariable myVar, std::vector &myInterpolationPoints, Crit3DInterpolationSettings *mySettings, float x, float y, float z, int maxNrPoints, float* devSt, float* avgDeltaZ, float* minDistance); float interpolate(std::vector &myPoints, Crit3DInterpolationSettings *mySettings, Crit3DMeteoSettings *meteoSettings, meteoVariable myVar, float myX, float myY, float myZ, std::vector myProxyValues, bool excludeSupplemental); @@ -98,6 +98,9 @@ bool isThermal(meteoVariable myVar); bool getUseTdVar(meteoVariable myVar); + unsigned sortPointsByDistance(unsigned maxNrPoints, std::vector &pointList, + std::vector &validPointList); + float getFirstIntervalHeightValue(std::vector &myPoints, bool useLapseRateCode); bool regressionGeneric(std::vector &myPoints, Crit3DInterpolationSettings* mySettings, diff --git a/agrolib/interpolation/spatialControl.cpp b/agrolib/interpolation/spatialControl.cpp index 1493c131..70a93445 100644 --- a/agrolib/interpolation/spatialControl.cpp +++ b/agrolib/interpolation/spatialControl.cpp @@ -341,7 +341,7 @@ bool checkData(Crit3DQuality* myQuality, meteoVariable myVar, Crit3DMeteoPoint* for (int i = 0; i < nrMeteoPoints; i++) { meteoPoints[i].currentValue = meteoPoints[i].elaboration; - if (isEqual(meteoPoints[i].currentValue, NODATA)) + if (! isEqual(meteoPoints[i].currentValue, NODATA)) meteoPoints[i].quality = quality::accepted; else meteoPoints[i].quality = quality::missing_data; @@ -353,7 +353,7 @@ bool checkData(Crit3DQuality* myQuality, meteoVariable myVar, Crit3DMeteoPoint* for (int i = 0; i < nrMeteoPoints; i++) { meteoPoints[i].currentValue = meteoPoints[i].anomaly; - if (isEqual(meteoPoints[i].currentValue, NODATA)) + if (! isEqual(meteoPoints[i].currentValue, NODATA)) meteoPoints[i].quality = quality::accepted; else meteoPoints[i].quality = quality::missing_data; diff --git a/agrolib/mathFunctions/commonConstants.h b/agrolib/mathFunctions/commonConstants.h index 8c3efbf3..f37fd5ec 100644 --- a/agrolib/mathFunctions/commonConstants.h +++ b/agrolib/mathFunctions/commonConstants.h @@ -101,7 +101,9 @@ #define BOUNDARY_FREEDRAINAGE 3 #define BOUNDARY_FREELATERALDRAINAGE 4 #define BOUNDARY_PRESCRIBEDTOTALPOTENTIAL 5 - #define BOUNDARY_CULVERT 6 + #define BOUNDARY_URBAN 10 + #define BOUNDARY_ROAD 11 + #define BOUNDARY_CULVERT 12 #define BOUNDARY_HEAT_SURFACE 10 #define BOUNDARY_SOLUTEFLUX 30 diff --git a/agrolib/mathFunctions/furtherMathFunctions.cpp b/agrolib/mathFunctions/furtherMathFunctions.cpp index bd13c1d1..80330e28 100644 --- a/agrolib/mathFunctions/furtherMathFunctions.cpp +++ b/agrolib/mathFunctions/furtherMathFunctions.cpp @@ -2804,13 +2804,16 @@ namespace interpolation mySSE += error * error; } int iterationNr = 0; + double pivot, mult, top; + std::vector firstEst(nrData); + std::vector> P(nrParameters, std::vector(nrData)); do { - double pivot, mult, top; + std::vector g(nrParameters,0); - std::vector firstEst(nrData); + std::vector> a(nrParameters, std::vector(nrParameters,0)); - std::vector> P(nrParameters, std::vector(nrData)); + //std::vector> weightsP(nrParameters, std::vector(nrData)); // matrix P corresponds to the Jacobian diff --git a/agrolib/project/project.cpp b/agrolib/project/project.cpp index 99ae3cc9..a8940c85 100644 --- a/agrolib/project/project.cpp +++ b/agrolib/project/project.cpp @@ -2909,6 +2909,7 @@ bool Project::interpolationDemLocalDetrending(meteoVariable myVar, const Crit3DT return true; } + bool Project::interpolationDemGlocalDetrending(meteoVariable myVar, const Crit3DTime& myTime, gis::Crit3DRasterGrid *myRaster) { if (!getUseDetrendingVar(myVar) || !interpolationSettings.getUseGlocalDetrending()) @@ -2971,15 +2972,16 @@ bool Project::interpolationDemGlocalDetrending(meteoVariable myVar, const Crit3D for (unsigned areaIndex = 0; areaIndex < interpolationSettings.getMacroAreas().size(); areaIndex++) { - //load macro area and its cells + // load macro area and its cells Crit3DMacroArea myArea = interpolationSettings.getMacroAreas()[areaIndex]; areaCells = myArea.getAreaCells(); std::vector subsetInterpolationPoints; + double interpolatedValue = NODATA; - if (!areaCells.empty()) + if (! areaCells.empty()) { macroAreaDetrending(myArea, myVar, interpolationPoints, subsetInterpolationPoints, elevationPos); - //calculate value for every cell + // calculate value for every cell for (unsigned cellIndex = 0; cellIndex < areaCells.size(); cellIndex = cellIndex + 2) { row = unsigned(areaCells[cellIndex]/DEM.header->nrCols); @@ -2992,12 +2994,16 @@ bool Project::interpolationDemGlocalDetrending(meteoVariable myVar, const Crit3D getProxyValuesXY(x, y, &interpolationSettings, proxyValues); - if (isEqual(myRaster->value[row][col], NODATA)) - myRaster->value[row][col] = interpolate(subsetInterpolationPoints, &interpolationSettings, meteoSettings, - myVar, x, y, z, proxyValues, true)*areaCells[cellIndex+1]; - else - myRaster->value[row][col] += interpolate(subsetInterpolationPoints, &interpolationSettings, meteoSettings, - myVar, x, y, z, proxyValues, true)*areaCells[cellIndex+1]; + interpolatedValue = interpolate(subsetInterpolationPoints, &interpolationSettings, meteoSettings, + myVar, x, y, z, proxyValues, true); + + if (!isEqual(interpolatedValue, NODATA)) + { + if (isEqual(myRaster->value[row][col], NODATA)) + myRaster->value[row][col] = interpolatedValue*areaCells[cellIndex+1]; + else + myRaster->value[row][col] += interpolatedValue*areaCells[cellIndex+1]; + } } } } diff --git a/agrolib/soil/soilDbTools.cpp b/agrolib/soil/soilDbTools.cpp index 1cbb95a7..592a020f 100644 --- a/agrolib/soil/soilDbTools.cpp +++ b/agrolib/soil/soilDbTools.cpp @@ -414,7 +414,6 @@ bool loadSoil(const QSqlDatabase &dbSoil, const QString &soilCode, soil::Crit3DS } mySoil.totalDepth = mySoil.horizon[mySoil.nrHorizons-1].lowerDepth; - } else { diff --git a/agrolib/soilFluxes3D/header/types.h b/agrolib/soilFluxes3D/header/types.h index 1d4bfaf5..87bf063f 100644 --- a/agrolib/soilFluxes3D/header/types.h +++ b/agrolib/soilFluxes3D/header/types.h @@ -13,7 +13,7 @@ struct Tboundary { short type; - float slope; /*!< [m m-1] */ + float slope; /*!< [m m-1] */ float boundaryArea; /*!< [m2] (only for surface runoff [m]) */ double waterFlow; /*!< [m3 s-1] */ double sumBoundaryWaterFlow; /*!< [m3] sum of boundary water flow */ diff --git a/agrolib/soilFluxes3D/water.cpp b/agrolib/soilFluxes3D/water.cpp index 15a7890a..f22f68a6 100644 --- a/agrolib/soilFluxes3D/water.cpp +++ b/agrolib/soilFluxes3D/water.cpp @@ -131,7 +131,20 @@ double infiltration(long sup, long inf, TlinkedNode *link, double deltaT) if (maxInfiltrationRate <= 0.0) return(0.0); /*! first soil layer: mean between current k and k_sat */ - double meanK = computeMean(nodeListPtr[inf].k, nodeListPtr[inf].Soil->K_sat); + double meanK = computeMean(nodeListPtr[inf].Soil->K_sat, nodeListPtr[inf].k); + + if (nodeListPtr[inf].boundary != nullptr) + { + if (nodeListPtr[inf].boundary->type == BOUNDARY_URBAN) + { + // TODO improve with external parameters + meanK *= 0.1; + } + else if (nodeListPtr[inf].boundary->type == BOUNDARY_ROAD) + { + meanK = 0.0; + } + } double dH = nodeListPtr[sup].H - nodeListPtr[inf].H; double maxK = maxInfiltrationRate * (cellDistance / dH); @@ -144,6 +157,19 @@ double infiltration(long sup, long inf, TlinkedNode *link, double deltaT) /*! saturated */ else { + if (nodeListPtr[inf].boundary != nullptr) + { + if (nodeListPtr[inf].boundary->type == BOUNDARY_URBAN) + { + // TODO check? + return(nodeListPtr[inf].Soil->K_sat * 0.1 * link->area) / cellDistance; + } + else if (nodeListPtr[inf].boundary->type == BOUNDARY_ROAD) + { + return 0.; + } + } + return(nodeListPtr[inf].Soil->K_sat * link->area) / cellDistance; } diff --git a/bin/CRITERIAGEO/mainWindow.cpp b/bin/CRITERIAGEO/mainWindow.cpp index 8de212f4..eff03034 100644 --- a/bin/CRITERIAGEO/mainWindow.cpp +++ b/bin/CRITERIAGEO/mainWindow.cpp @@ -1552,11 +1552,11 @@ void MainWindow::on_actionClipRaster_with_raster_triggered() // select raster QString refRasterFileName; bool isOk; - gis::Crit3DRasterGrid *refRaster = selectRaster("Select reference raster", refRasterFileName, isOk); + gis::Crit3DRasterGrid *refRaster = selectRaster("Reference raster", refRasterFileName, isOk); if (! isOk) return; QString maskRasterFileName; - gis::Crit3DRasterGrid *maskRaster = selectRaster("Select mask raster", maskRasterFileName, isOk); + gis::Crit3DRasterGrid *maskRaster = selectRaster("Mask raster", maskRasterFileName, isOk); if (! isOk) return; gis::Crit3DRasterGrid* outputRaster = new gis::Crit3DRasterGrid();