// Sets only flowDir only where there is a positive slope // Returns number of cells which are flat int setPosDir(linearpart<float>& elevDEM, linearpart<short>& flowDir) { double dxA = elevDEM.getdxA(); double dyA = elevDEM.getdyA(); int nx = elevDEM.getnx(); int ny = elevDEM.getny(); int numFlat = 0; double tempdxc, tempdyc; fact = new double*[ny]; // initialize 2d array by Nazmus 2/16 for(int m = 0; m<ny; m++) fact[m] = new double[9]; for (int m = 0; m<ny; m++) { for (int k = 1; k <= 8; k++) { elevDEM.getdxdyc(m, tempdxc, tempdyc); fact[m][k] = (double) (1./sqrt(d1[k]*d1[k]*tempdxc*tempdxc + d2[k]*d2[k]*tempdyc*tempdyc)); } } for (int j = 0; j < ny; j++) { for (int i=0; i < nx; i++) { //FlowDir is nodata if it is on the border OR elevDEM has no data if (elevDEM.isNodata(i,j) || !elevDEM.hasAccess(i-1,j) || !elevDEM.hasAccess(i+1,j) || !elevDEM.hasAccess(i,j-1) || !elevDEM.hasAccess(i,j+1)) { //do nothing continue; } //Check if cell is "contaminated" (neighbors have no data) // set flowDir to noData if contaminated bool contaminated = false; for (int k=1; k<=8; k++) { int in=i+d1[k]; int jn=j+d2[k]; if (elevDEM.isNodata(in,jn)) { contaminated = true; break; } } if (contaminated) { flowDir.setToNodata(i,j); } else { // If cell is not contaminated, flowDir.setData(i, j, 0); setFlow(i,j, flowDir, elevDEM); if (flowDir.getData(i,j) == 0) { numFlat++; } } } } return numFlat; }
long setPosDirDinf(linearpart<float>& elevDEM, linearpart<float>& flowDir, linearpart<float>& slope, int useflowfile) { double dxA = elevDEM.getdxA(); double dyA = elevDEM.getdyA(); long nx = elevDEM.getnx(); long ny = elevDEM.getny(); float tempFloat; double tempdxc, tempdyc; int i, j, k, in, jn, con; long numFlat = 0; tempFloat = 0; for (j = 0; j < ny; j++) { for (i = 0; i < nx; i++) { //FlowDir is nodata if it is on the border OR elevDEM has no data if (elevDEM.isNodata(i, j) || !elevDEM.hasAccess(i - 1, j) || !elevDEM.hasAccess(i + 1, j) || !elevDEM.hasAccess(i, j - 1) || !elevDEM.hasAccess(i, j + 1)) { //do nothing } else { //Check if cell is "contaminated" (neighbors have no data) // set flowDir to noData if contaminated con = 0; for (k = 1; k <= 8 && con != -1; k++) { in = i + d1[k]; jn = j + d2[k]; if (elevDEM.isNodata(in, jn)) con = -1; } if (con == -1) flowDir.setToNodata(i, j); //If cell is not contaminated, else { tempFloat = -1.; flowDir.setData(i, j, tempFloat); //set to -1 elevDEM.getdxdyc(j, tempdxc, tempdyc); float DXX[3] = {0, tempdxc, tempdyc}; //tardemlib.cpp ln 1291 float DD = sqrt(tempdxc * tempdxc + tempdyc * tempdyc); //tardemlib.cpp ln 1293 SET2(j, i, DXX, DD, elevDEM, flowDir, slope); //i=y in function form old code j is x switched on purpose // Use SET2 from serial code here modified to get what it has as felevg.d from elevDEM partition // Modify to return 0 if there is a 0 slope. Modify SET2 to output flowDIR as no data (do nothing // if verified initialization to nodata) and // slope as 0 if a positive slope is not found //setFlow( i,j, flowDir, elevDEM, area, useflowfile); if (flowDir.getData(i, j, tempFloat) == -1) numFlat++; } } } } return numFlat; }
//Calculate the slope information of flowDir to slope void calcSlope(linearpart<short>& flowDir, linearpart<float>& elevDEM, linearpart<float>& slope) { int nx = elevDEM.getnx(); int ny = elevDEM.getny(); for (int j=0; j < ny; j++) { for (int i=0; i < nx; i++) { // If i,j is on the border or flowDir has no data, set slope(i,j) to slopeNoData if (flowDir.isNodata(i,j) || !flowDir.hasAccess(i-1,j) || !flowDir.hasAccess(i+1,j) || !flowDir.hasAccess(i,j-1) || !flowDir.hasAccess(i,j+1)) { slope.setToNodata(i, j); } else { short flowDirection = flowDir.getData(i,j); int in = i + d1[flowDirection]; int jn = j + d2[flowDirection]; float elevDiff = elevDEM.getData(i,j) - elevDEM.getData(in,jn); slope.setData(i,j, elevDiff*fact[j][flowDirection]); } } } }
int markPits(T& elevDEM, linearpart<float>& flowDir, std::vector<std::vector<node>>&islands, SparsePartition<short>& inc) { int nx = flowDir.getnx(); int ny = flowDir.getny(); int numPits = 0; //There are pits remaining - set direction to no data for (auto& island : islands) { for (node flat : island) { bool skip = false; for (int k=1; k<=8; k++) { if (dontCross(k, flat.x, flat.y, flowDir)==0) { int jn = flat.y + d2[k]; int in = flat.x + d1[k]; if (!flowDir.hasAccess(in, jn)) continue; auto elevDiff = elevDEM.getData(flat.x, flat.y) - elevDEM.getData(in, jn); float flow = flowDir.getData(in, jn); // Adjacent cell drains and is equal or lower in elevation so this is a low boundary if (elevDiff >= 0 && flow == -1) { skip = true; break; } else if (flow == -1) { // If neighbor is in flat // FIXME: check if this is correct if (inc.getData(in,jn) >= 0){ // && inc.getData(in,jn)<st) { skip = true; break; } } } } // mark pit if (!skip) { numPits++; flowDir.setToNodata(flat.x, flat.y); } } } return numPits; }
void flowTowardsLower(T& elev, linearpart<float>& flowDir, std::vector<std::vector<node>>&islands, SparsePartition<short>& inc) { long nx = flowDir.getnx(); long ny = flowDir.getny(); std::vector<node> lowBoundaries; // Find low boundaries. for(auto& island : islands) { for(node flat : island) { float flatElev = elev.getData(flat.x, flat.y); for (int k = 1; k <= 8; k++) { if (dontCross(k, flat.x, flat.y, flowDir) == 0) { int in = flat.x + d1[k]; int jn = flat.y + d2[k]; if (!flowDir.hasAccess(in, jn)) continue; auto elevDiff = flatElev - elev.getData(in,jn); float flow = flowDir.getData(in, jn); bool edgeDrain = flowDir.isNodata(in, jn); // Adjacent cell drains and is equal or lower in elevation so this is a low boundary if ((elevDiff >= 0 && flow >= 0.0) || edgeDrain) { lowBoundaries.push_back(flat); inc.setData(flat.x, flat.y, -1); // No need to check the other neighbors break; } } } } } size_t numInc = propagateIncrements(flowDir, inc, lowBoundaries); // Not all grid cells were resolved - pits remain // Remaining grid cells are unresolvable pits if (numInc > 0) { markPits(elev, flowDir, islands, inc); } }
void setFlow2(int i, int j, linearpart<short>& flowDir, T& elev, SparsePartition<int>& inc) { /* This function sets directions based upon secondary elevations for assignment of flow directions across flats according to Garbrecht and Martz scheme. There are two possibilities: A. The neighbor is outside the flat set B. The neighbor is in the flat set. In the case of A the input elevations are used and if a draining neighbor is found it is selected. Case B requires slope to be positive. Remaining flats are removed by iterating this process */ int nx = flowDir.getnx(); int ny = flowDir.getny(); const short order[8]= {1,3,5,7,2,4,6,8}; float slopeMax = 0; for (short k : order) { int in = i+d1[k]; int jn = j+d2[k]; if (!flowDir.hasAccess(in, jn)) continue; if (inc.getData(in, jn) > 0) { // Neighbor is in flat float slope = fact[j][k]*(inc.getData(i, j) - inc.getData(in, jn)); if (slope > slopeMax) { flowDir.setData(i, j, k); slopeMax = slope; } } else { // Neighbor is not in flat auto ed = elev.getData(i, j) - elev.getData(in, jn); if (ed >= 0) { // Found a way out - this is outlet flowDir.setData(i, j, k); break; } } } }
void flowFromHigher(T& elev, linearpart<float>& flowDir, std::vector<std::vector<node>>&islands, SparsePartition<short>& inc) { long nx = flowDir.getnx(); long ny = flowDir.getny(); // Find high boundaries for (auto& island : islands) { std::vector<node> highBoundaries; for (node flat : island) { float flatElev = elev.getData(flat.x, flat.y); bool highBoundary = false; for (int k = 1; k <= 8; k++) { if (dontCross(k, flat.x, flat.y, flowDir) == 0) { int in = flat.x + d1[k]; int jn = flat.y + d2[k]; if (!flowDir.hasAccess(in, jn)) continue; auto elevDiff = flatElev - elev.getData(in, jn); if (elevDiff < 0) { // Adjacent cell has higher elevation so this is a high boundary highBoundary = true; break; } } } if (highBoundary) { inc.setData(flat.x, flat.y, -1); highBoundaries.push_back(flat); } } propagateIncrements(flowDir, inc, highBoundaries); } }