static inline double Terrain_Slope_RiseRun(const Array2D<T> &elevations, const int x, const int y, const float zscale){ const auto tsv = TerrainSetup(elevations,x,y,zscale); //See p. 18 of Horn (1981) double dzdx = ( (tsv.c+2*tsv.f+tsv.i) - (tsv.a+2*tsv.d+tsv.g) ) / 8 / elevations.getCellLengthX(); double dzdy = ( (tsv.g+2*tsv.h+tsv.i) - (tsv.a+2*tsv.b+tsv.c) ) / 8 / elevations.getCellLengthY(); //The above fits are surface to a 3x3 neighbour hood. This returns the slope //along the direction of maximum gradient. return sqrt(dzdx*dzdx+dzdy*dzdy); }
static inline double Terrain_Aspect(const Array2D<T> &elevations, const int x, const int y, const float zscale){ const auto tsv = TerrainSetup(elevations,x,y,zscale); //See p. 18 of Horn (1981) double dzdx = ( (tsv.c+2*tsv.f+tsv.i) - (tsv.a+2*tsv.d+tsv.g) ) / 8 / elevations.getCellLengthX(); double dzdy = ( (tsv.g+2*tsv.h+tsv.i) - (tsv.a+2*tsv.b+tsv.c) ) / 8 / elevations.getCellLengthY(); double the_aspect = 180.0/M_PI*atan2(dzdy,-dzdx); if(the_aspect<0) return 90-the_aspect; else if(the_aspect>90.0) return 360.0-the_aspect+90.0; else return 90.0-the_aspect; }
static inline TA_Setup_Curves_Vars TerrainCurvatureSetup(const Array2D<T> &elevations, const int x, const int y, const float zscale){ const TA_Setup_Vars tsv = TerrainSetup(elevations, x, y, zscale); TA_Setup_Curves_Vars tscv; //Z1 Z2 Z3 a b c //Z4 Z5 Z6 d e f //Z7 Z8 Z9 g h i //Curvatures in the manner of Zevenbergen and Thorne 1987 tscv.L = elevations.getCellLengthX(); tscv.D = ( (tsv.d+tsv.f)/2 - tsv.e) / tscv.L / tscv.L; //D = [(Z4 + Z6) /2 - Z5] / L^2 tscv.E = ( (tsv.b+tsv.h)/2 - tsv.e) / tscv.L / tscv.L; //E = [(Z2 + Z8) /2 - Z5] / L^2 tscv.F = (-tsv.a+tsv.c+tsv.g-tsv.i)/4/tscv.L/tscv.L; //F = (-Z1+Z3+Z7-Z9)/(4L^2) tscv.G = (-tsv.d+tsv.f)/2/tscv.L; //G = (-Z4+Z6)/(2L) tscv.H = (tsv.b-tsv.h)/2/tscv.L; //H = (Z2-Z8)/(2L) return tscv; }
static inline void TerrainProcessor(F func, const Array2D<T> &elevations, const float zscale, Array2D<float> &output){ if(elevations.getCellLengthX()!=elevations.getCellLengthY()) RDLOG_WARN<<"Cell X and Y dimensions are not equal!"; output.resize(elevations); ProgressBar progress; progress.start(elevations.size()); #pragma omp parallel for for(int y=0;y<elevations.height();y++){ progress.update(y*elevations.width()); for(int x=0;x<elevations.width();x++) if(elevations.isNoData(x,y)) output(x,y) = output.noData(); else output(x,y) = func(elevations,x,y,zscale); } RDLOG_TIME_USE<<"Wall-time = "<<progress.stop(); }