void testBilateralFilter( const Array2D< float >& input, float ss, float sr, Array2D< float >& output ) { BilateralFilter bf( input.width(), input.height(), ss, sr ); int nIterations = 100; bf.setInput( input ); StopWatch sw; for( int i = 0; i < nIterations; ++i ) { bf.apply( ); cudaDeviceSynchronize(); } float ms = sw.millisecondsElapsed(); bf.getOutput( output ); printf( "image size: %d x %d\n", input.width(), input.height() ); printf( "ss = %f, sr = %f\n", ss, sr ); printf( "Total time = %f ms, ms on average: %f\n", ms, ms / nIterations ); }
void d8_flow_directions( const Array2D<T> &elevations, Array2D<U> &flowdirs ){ ProgressBar progress; std::cerr<<"A D8 Flow Directions"<<std::endl; std::cerr<<"C TODO"<<std::endl; std::cerr<<"p Setting up the flow directions matrix..."<<std::endl; flowdirs.resize(elevations); flowdirs.setAll(NO_FLOW); flowdirs.setNoData(FLOWDIR_NO_DATA); std::cerr<<"p Calculating D8 flow directions..."<<std::endl; progress.start( elevations.width()*elevations.height() ); #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(x,y)==elevations.noData()) flowdirs(x,y) = flowdirs.noData(); else flowdirs(x,y) = d8_FlowDir(elevations,x,y); } std::cerr<<"t Succeeded in = "<<progress.stop()<<" s"<<std::endl; }
void TA_CTI( const Array2D<T> &flow_accumulation, const Array2D<U> &riserun_slope, Array2D<V> &result ){ Timer timer; RDLOG_ALG_NAME<<"d8_CTI"; if(flow_accumulation.width()!=riserun_slope.width() || flow_accumulation.height()!=riserun_slope.height()) throw std::runtime_error("Couldn't calculate CTI! The input matricies were of unequal dimensions!"); RDLOG_PROGRESS<<"Setting up the CTI matrix..."<<std::flush; result.resize(flow_accumulation); result.setNoData(-1); //Log(x) can't take this value of real inputs, so we're good RDLOG_PROGRESS<<"succeeded."; RDLOG_PROGRESS<<"Calculating CTI..."<<std::flush; timer.start(); #pragma omp parallel for collapse(2) for(int x=0;x<flow_accumulation.width();x++) for(int y=0;y<flow_accumulation.height();y++) if(flow_accumulation(x,y)==flow_accumulation.noData() || riserun_slope(x,y)==riserun_slope.noData()) result(x,y)=result.noData(); else result(x,y)=log( (flow_accumulation(x,y)/flow_accumulation.getCellArea()) / (riserun_slope(x,y)+0.001) ); RDLOG_TIME_USE<<"succeeded in "<<timer.stop()<<"s."; }
Array2D matrix_multiply(const Array2D &M1,const Array2D &M2) { if (M1.height()!=M2.width()) return Array2D(); Array2D ret(M1.width(),M2.height()); for (int j=0; j<ret.height(); j++) for (int i=0; i<ret.width(); i++) { double val=0; for (int k=0; k<M1.height(); k++) { val+=M1.value(i,k)*M2.value(k,j); } ret.setValue(val,i,j); } return ret; }
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(); }
int SpotLightFallOFFIntensityCalculator::GetNumberOfRadiusSegments(const Array2D<Rgba>& inputImage_, const Point2D<int>& corePoint_) { //Get Max distance from core point to all points in image int max1 = std::sqrt(powf(corePoint_.x, 2) + powf(corePoint_.y, 2)); int max2 = std::sqrt(powf(corePoint_.x - inputImage_.width(), 2) + powf(corePoint_.y - inputImage_.height(), 2)); int max3 = std::sqrt(powf(corePoint_.x - inputImage_.width(), 2) + powf(corePoint_.y, 2)); int max4 = std::sqrt(powf(corePoint_.x, 2) + powf(corePoint_.y - inputImage_.height(), 2)); int max = std::max(std::max(std::max(max1, max2), max3), max4); return (int)(max/BLOCKSIZE); }
void dinf_flow_flats( const Array2D<int32_t> &flat_resolution_mask, const Array2D<int32_t> &groups, Array2D<float> &flowdirs ) { ProgressBar progress; std::cerr<<"\n###Dinf Flow Flats"<<std::endl; std::cerr<<"%%Calculating Dinf flow directions using flat mask..."<<std::endl; progress.start( flat_resolution_mask.width()*flat_resolution_mask.height() ); #pragma omp parallel for for(int x=1; x<flat_resolution_mask.width()-1; x++) { progress.update( x*flat_resolution_mask.height() ); for(int y=1; y<flat_resolution_mask.height()-1; y++) if(flat_resolution_mask(x,y)==flat_resolution_mask.noData()) continue; else if(flowdirs(x,y)==NO_FLOW) flowdirs(x,y)=dinf_masked_FlowDir(flat_resolution_mask,groups,x,y); } std::cerr<<"Succeeded in "<<progress.stop()<<"s."<<std::endl; }
void testCrossBilateralFilter( const Array2D< float >& data, const Array2D< float >& edge, float ss, float sr, Array2D< float >& output ) { BilateralFilter cbf( data.width(), data.height(), ss, sr, 0.f, 1.f, true ); int nIterations = 100; StopWatch sw; for( int i = 0; i < nIterations; ++i ) { cbf.applyCross( data, edge, output ); cudaDeviceSynchronize(); } float ms = sw.millisecondsElapsed(); printf( "image size: %d x %d\n", data.width(), data.height() ); printf( "ss = %f, sr = %f\n", ss, sr ); printf( "Total time = %f ms, ms on average: %f\n", ms, ms / nIterations ); }
void dinf_flow_directions(const Array2D<T> &elevations, Array2D<float> &flowdirs){ ProgressBar progress; std::cerr<<"\nA Dinf Flow Directions"<<std::endl; std::cerr<<"C Tarboton, D.G. 1997. A new method for the determination of flow directions and upslope areas in grid digital elevation models. Water Resources Research. Vol. 33. pp 309-319."<<std::endl; std::cerr<<"p Setting up the Dinf flow directions matrix..."<<std::endl; flowdirs.resize(elevations); flowdirs.setNoData(dinf_NO_DATA); flowdirs.setAll(NO_FLOW); std::cerr<<"p Calculating Dinf flow directions..."<<std::endl; 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(x,y)==elevations.noData()) flowdirs(x,y) = flowdirs.noData(); else flowdirs(x,y) = dinf_FlowDir(elevations,x,y); } std::cerr<<"t Succeeded in = "<<progress.stop()<<" s"<<std::endl; }
int threshold(int th, Array2D &im) { int w = im.width(); int h = im.height(); int cnt=0; for (int i=0; i<h; ++i) { for (int j=0; j<w; ++j) { if (im[i][j] < th) { im[i][j] = 0; } else { im[i][j] = 255; ++cnt; } } } return cnt; }
void GridPerimToArray(const Array2D<U> &grid, std::vector<U> &vec){ assert(vec.size()==0); //Ensure receiving array is empty std::vector<U> vec2copy; vec2copy = grid.getRowData(0); //Top vec.insert(vec.end(),vec2copy.begin(),vec2copy.end()); vec2copy = grid.getColData(grid.width()-1); //Right vec.insert(vec.end(),vec2copy.begin()+1,vec2copy.end()); vec2copy = grid.getRowData(grid.height()-1); //Bottom vec.insert(vec.end(),vec2copy.begin(),vec2copy.end()-1); vec2copy = grid.getColData(0); //Left vec.insert(vec.end(),vec2copy.begin()+1,vec2copy.end()-1); }
void saveArrayAsImage( const Array2D< float >& array, QString prefix, float ss, float sr ) { Image4f im( array.width(), array.height() ); for( int y = 0; y < im.height(); ++y ) { for( int x = 0; x < im.width(); ++x ) { float v = array( x, y ); im.setPixel( x, y, Vector4f( v, v, v, 1 ) ); } } QString filename = QString( "%1_%2_%3.png" ).arg( prefix ).arg( ss ).arg( sr ); printf( "saving output: %s...", qPrintable( filename ) ); im.flipUD().save( filename ); printf( "done.\n\n" ); }
void FindFlats( const Array2D<T> &elevations, Array2D<int8_t> &flats ){ flats.resize(elevations); flats.setNoData(FLAT_NO_DATA); ProgressBar progress; progress.start( elevations.size() ); #pragma omp parallel for for(int y=0;y<elevations.height();y++) for(int x=0;x<elevations.width();x++){ if(elevations.isNoData(x,y)){ flats(x,y) = FLAT_NO_DATA; continue; } if(elevations.isEdgeCell(x,y)){ flats(x,y) = NOT_A_FLAT; continue; } //We'll now assume that the cell is a flat unless proven otherwise flats(x,y) = IS_A_FLAT; for(int n=1;n<=8;n++){ const int nx = x+dx[n]; const int ny = y+dy[n]; if(elevations(nx,ny)<elevations(x,y) || elevations.isNoData(nx,ny)){ flats(x,y) = NOT_A_FLAT; break; } } //We handled the base case just above the for loop } RDLOG_TIME_USE<<"Succeeded in = "<<progress.stop()<<" s"; }
void SpotLightFallOFFIntensityCalculator::GetLightFallOffPointsfromCorePoints_UsingGradientEstimation(const Array2D<Rgba>& inputImage_, const Point2D<int>& corePoint_) { int imageHeight = (int)inputImage_.height(); int imageWidth = (int)inputImage_.width(); UtilityClass* util = new UtilityClass(); Rgba* outputPixels = util->GetImagePixelsToWrite(imageWidth, imageHeight); Array2D<Rgba> outputImage(imageHeight,imageWidth); Array2D<Rgba> outputImage1(imageHeight,imageWidth); ImageFilterFactoryClass* imageFilterFactoryClass = new ImageFilterFactoryClass(); ImageFilterClass* imageFilterClass = imageFilterFactoryClass->GetImageFilterClass(inputImage_, 5, FILTERTYPE::GAUSSIAN); imageFilterClass->ProcessImage(inputImage_, outputImage); imageFilterClass = imageFilterFactoryClass->GetImageFilterClass(outputImage, 1, FILTERTYPE::SOBEL); imageFilterClass->ProcessImage(outputImage,outputImage1); // imageFilterClass = imageFilterFactoryClass->GetImageFilterClass(inputImage_, 2, FILTERTYPE::GAUSSIAN); // imageFilterClass->ProcessImage(outputImage1, outputImage); // // imageFilterClass = imageFilterFactoryClass->GetImageFilterClass(outputImage, 1, FILTERTYPE::SOBEL); // imageFilterClass->ProcessImage(outputImage,outputImage1); for (int row = 0; row < (imageHeight); ++row) { for (int col = 0; col < (imageWidth); ++col) { int i = row * imageWidth + col; outputPixels[i] = outputImage1[row][col]; } } util->WriteImage2DArrayPixels("../../Output/LOG1.exr", outputPixels, imageWidth, imageHeight); delete util; delete imageFilterFactoryClass; }
void Array2DPrivate::copy_from(const Array2D &X) { allocate(X.width(),X.height()); long N=X.width()*X.height(); for (long ii=0; ii<N; ii++) m_data[ii]=X.d->m_data[ii]; }
void SpotLightFallOFFIntensityCalculator::GetLightFallOffPointsfromCorePoints_UsingBlocksOfPixels(const Array2D<Rgba>& inputImage_, const Point2D<int>& corePoint_) { int imageWidth = (int)inputImage_.width(); int imageHeight = (int)inputImage_.height(); UtilityClass* util = new UtilityClass(); Point2D<int> currPoint = corePoint_; Point2D<int> corePoint = corePoint_; int block = 1; double currBlockIntensity = 0; double prevBlockIntensity = 0; double currPixelWindowIntensity = 0; // Loop through 0 to 360 for (int degree = 0; degree < 360; ++degree) { currPoint = corePoint_; block = 1; currBlockIntensity = 0; std::cout << "*********** degree = " << degree << std::endl; while ((currPoint.x >= 0) && (currPoint.x < imageWidth) && (currPoint.y >= 0) && (currPoint.y < imageHeight)) { prevBlockIntensity = currBlockIntensity; currBlockIntensity = 0; for (int radius = block; radius <=(block+BLOCKSIZE); ++radius) { currPoint = const_cast<Point2D<int>&>(corePoint_) + Point2D<int>(radius * cos(degree), radius * sin(degree)); //currPoint = corePoint + Point2D<double>(radius*cos(degree), radius*sin(degree)); if ((currPoint.x < 0) || (currPoint.x > imageWidth) || (currPoint.y < 0) || (currPoint.y > imageHeight)) { break; } currPixelWindowIntensity = 0; util->GetAveragePixelIntensityAroundaPoint(inputImage_, currPoint, WINDOWRADIUS); currBlockIntensity += currPixelWindowIntensity; //currBlockIntensity += inputImage->at<uchar>(currPoint.y,currPoint.x); } currBlockIntensity /= BLOCKSIZE; double intensityDifference = prevBlockIntensity - currBlockIntensity; std::cout << "intensity difference = " << intensityDifference << std::endl; //if ((intensityDifference > 2 && intensityDifference < 5) && (block != 1)) { /* if ((intensityDifference >= 5 && intensityDifference <= 8) && (block != 1)) { if ((currPoint.x >= 0) && (currPoint.x < imageWidth) && (currPoint.y >= 0) && (currPoint.y < imageHeight)) { cv::circle(refImage, currPoint, 2, cv::Scalar(0,0,255), -1); } } if ((intensityDifference >= 10 && intensityDifference <= 15) && (block != 1)) { if ((currPoint.x >= 0) && (currPoint.x < imageWidth) && (currPoint.y >= 0) && (currPoint.y < imageHeight)) { cv::circle(refImage, currPoint, 2, cv::Scalar(0,255,255), -1); } } */ block += BLOCKSIZE; } } return; }
static float dinf_FlowDir(const Array2D<T> &elevations, const int x, const int y){ //Ensure that flow is pulled off the edge of the grid if (elevations.isEdgeCell(x,y)){ if(x==0 && y==0) return 3*M_PI/4; //D8: 2 else if(x==0 && y==elevations.height()-1) return 5*M_PI/4; //D8: 8 else if(x==elevations.width()-1 && y==0) return 1*M_PI/4; //D8: 4 else if(x==elevations.width()-1 && y==elevations.height()-1) return 7*M_PI/4; //D8: 6 else if(x==0) return 4*M_PI/4; //D8: 1 else if(x==elevations.width()-1) return 0*M_PI/4; //D8: 5 else if(y==0) return 2*M_PI/4; //D8: 3 else if(y==elevations.height()-1) return 6*M_PI/4; //D8: 7 } int nmax = -1; double smax = 0; double rmax = 0; //I am not on the edge of the grid. All my neighbours can be examined. for(int n=0;n<8;n++){ //Is is assumed that cells with a value of NoData have very negative //elevations with the result that they draw flow off of the grid. //Choose elevations based on Table 1 of Tarboton (1997), Barnes TODO const double e0 = elevations(x,y); const double e1 = elevations(x+dx_e1[n],y+dy_e1[n]); const double e2 = elevations(x+dx_e2[n],y+dy_e2[n]); //TODO: Assumes that the width and height of grid cells are equal and scaled //to 1. const double d1 = 1; const double d2 = 1; const double s1 = (e0-e1)/d1; const double s2 = (e1-e2)/d2; double r = atan2(s2,s1); double s; if(r<0){ r = 0; s = s1; } else if(r>atan2(d2,d1)){ r = atan2(d2,d1); //TODO: This is a constant s = (e0-e2)/sqrt(d1*d1+d2*d2); } else { s = sqrt(s1*s1+s2*s2); } if(s>smax){ smax = s; nmax = n; rmax = r; } } double rg = NO_FLOW; if(nmax!=-1) rg = (af[nmax]*rmax+ac[nmax]*M_PI/2); return rg; }
void SpotLightFallOFFIntensityCalculator::GetLightFallOffPointsfromCorePoints_UsingTableMapOfSectorsAndSegment(const Array2D<Rgba>& inputImage_, const Point2D<int>&corePoint_) { // Create a Table with Degree and radius // PixelInSegment[degree][radius] -> vector of pixels. int maxNumberOfRadiusSegment = GetNumberOfRadiusSegments(inputImage_, corePoint_); InitializeSectorsOfImage(inputImage_, corePoint_); int numOfRows = (int)inputImage_.height(); int numOfCols = (int)inputImage_.width(); for (int row=0; row < numOfRows; ++row) { for (int col = 0; col < numOfCols; ++col) { // Which pixel belongs to which sector and which segment // Get distance from corePoint_; if (row == corePoint_.y && col == corePoint_.x) { continue; } Point2D<int> currPixel = Point2D<int>((row - corePoint_.y),(col - corePoint_.x)); double distance = std::sqrt(powf(currPixel.x, 2) + powf(currPixel.y, 2)); int theta = (int)rad2deg(atan2(-currPixel.y, currPixel.x)); int block = (distance - 1) / (BLOCKSIZE ); if (theta < 0) { theta = 360 + theta; } Sector[theta][block].push_back(Point2D<int>(row,col)); SectorIntensity[theta][block].push_back(inputImage_[row][col]); } } GetFallOffRegionForNoAmbientLightBackground(maxNumberOfRadiusSegment); //GetIntensityDifferenceForEachSectorSegments(maxNumberOfRadiusSegment); /* // UtilityClass* util = new UtilityClass(); // Rgba* outputPixels = util->GetImagePixelsToWrite(numOfCols, numOfRows); // // std::vector<double>diffInIntensity = std::vector<double>(360,0); // // for (int index = 0; index < 360; ++index) { // for (int block = 1; block < (maxNumberOfRadiusSegment); ++block) { // // int numberOfZeroIntensityVectorBlock1 = 0, numberOfZeroIntensityVectorBlock2 = 0; // // if (Sector[index][block].size() > 0) { // // numberOfZeroIntensityVectorBlock1 = (int)std::count_if(SectorIntensity[index][block].begin(), SectorIntensity[index][block].end(), value_equal(Rgba(0, 0, 0))); // // std::cout << index << "-" << block << " = " << numberOfZeroIntensityVectorBlock1 << " total = " << SectorIntensity[index][block].size() << " normalized = " << (double)((double)numberOfZeroIntensityVectorBlock1/ (double)SectorIntensity[index][block].size()) << " -- " << Sector[index][block][0].y << "," << Sector[index][block][0].x << std::endl; // } // // else if (Sector[index][block-1].size() > 0) { // numberOfZeroIntensityVectorBlock2 = (int)std::count_if(SectorIntensity[index][block-1].begin(), SectorIntensity[index][block-1].end(), value_equal(Rgba(0, 0, 0))); // // std::cout << index << "-" << block-1 << " = " << numberOfZeroIntensityVectorBlock2 << " total = " << SectorIntensity[index][block-1].size() << " normalized = " << (double)((double)numberOfZeroIntensityVectorBlock2/ (double)SectorIntensity[index][block-1].size()) << " -- " << Sector[index][block-1][0].y << "," << Sector[index][block-1][0].x << std::endl; // } // // if (std::abs((int)Sector[index][block].size() - (int)Sector[index][block-1].size()) > 0) { // // // Sum of all pixel intensities in each block. // int avgSumOfElementsInFirstBlock = (std::accumulate(SectorIntensity[index][block].begin(),SectorIntensity[index][block].end(),0, Vector_acc))/((int)SectorIntensity[index][block].size() + EPSILON); // int avgSumOfElementsInSecondBlock = std::accumulate(SectorIntensity[index][block-1].begin(),SectorIntensity[index][block-1].end(),0, Vector_acc)/((int)SectorIntensity[index][block-1].size() + EPSILON); // // int averagePixelIntensityDifference = std::abs( avgSumOfElementsInFirstBlock - avgSumOfElementsInSecondBlock); // // if (Sector[index][block].size() > 0) { // std::cout << index << "::" << block << "::" << Sector[index][block][0].y << ","<< Sector[index][block][0].x << " = " << averagePixelIntensityDifference << std::endl; // } // else { // std::cout << index << "::" << block-1 << "::" << Sector[index][block-1][0].y << ","<< Sector[index][block-1][0].x << " = " << averagePixelIntensityDifference << std::endl; // } // // if (averagePixelIntensityDifference > diffInIntensity[index]) { // diffInIntensity[index] = averagePixelIntensityDifference; // std::cout << "Overall difference in intensity = " ; // if (Sector[index][block].size() > 0) { // // std::cout << index << "::" << block << "::" << Sector[index][block][0].y << ","<< Sector[index][block][0].x << " = " << diffInIntensity[index] << std::endl; // } // else { // std::cout << index << "::" << block << "::" << Sector[index][block-1][0].y << ","<< Sector[index][block-1][0].x << " = " << diffInIntensity[index] << std::endl; // } // } // } // } // } // // // for (int index = 0; index <360; ++index) { // for (int pixelIndex = 0; pixelIndex < Sector[index][5].size(); ++pixelIndex) { // int i = Sector[index][5][pixelIndex].y * numOfCols + Sector[index][5][pixelIndex].x; // outputPixels[i].r = 1.0; // std::cout << Sector[index][5][pixelIndex].y << "," << Sector[index][5][pixelIndex].x << " "; // } // std::cout << std::endl; // } // util->WriteImage2DArrayPixels("output-angle90.exr", outputPixels, numOfCols, numOfRows); // // delete[] outputPixels; // delete util; */ }
void dinf_upslope_area( const Array2D<T> &flowdirs, Array2D<U> &area ){ Array2D<int8_t> dependency; std::queue<GridCell> sources; ProgressBar progress; std::cerr<<"\nA D-infinity Upslope Area"<<std::endl; std::cerr<<"C Tarboton, D.G. 1997. A new method for the determination of flow directions and upslope areas in grid digital elevation models. Water Resources Research. Vol. 33. pp 309-319."<<std::endl; std::cerr<<"p Setting up the dependency matrix..."<<std::endl; dependency.resize(flowdirs); dependency.setAll(0); std::cerr<<"p Setting up the area matrix..."<<std::endl; area.resize(flowdirs); area.setAll(0); area.setNoData(dinf_NO_DATA); bool has_cells_without_flow_directions=false; std::cerr<<"p Calculating dependency matrix & setting noData() cells..."<<std::endl; progress.start( flowdirs.size() ); /////////////////////// //Calculate the number of "dependencies" each cell has. That is, count the //number of cells which flow into each cell. #pragma omp parallel for reduction(|:has_cells_without_flow_directions) for(int y=0;y<flowdirs.height();y++){ progress.update( y*flowdirs.width() ); for(int x=0;x<flowdirs.width();x++){ //If the flow direction of the cell is NoData, mark its area as NoData if(flowdirs.isNoData(x,y)){ area(x,y) = area.noData(); dependency(x,y) = 9; //TODO: This is an unnecessary safety precaution. This prevents the cell from ever being enqueued (an unnecessary safe guard? TODO) continue; //Only necessary if there are bugs below (TODO) } //If the cell has no flow direction, note that so we can warn the user if(flowdirs(x,y)==NO_FLOW){ has_cells_without_flow_directions=true; continue; } //TODO: More explanation of what's going on here int n_high, n_low; int nhx,nhy,nlx,nly; where_do_i_flow(flowdirs(x,y),n_high,n_low); nhx=x+dinf_dx[n_high]; nhy=y+dinf_dy[n_high]; if(n_low!=-1){ nlx = x+dinf_dx[n_low]; nly = y+dinf_dy[n_low]; } if( n_low!=-1 && flowdirs.inGrid(nlx,nly) && flowdirs(nlx,nly)!=flowdirs.noData() ) dependency(nlx,nly)++; if( flowdirs.inGrid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.noData() ) dependency(nhx,nhy)++; } } std::cerr<<"t Succeeded in = "<<progress.stop()<<" s"<<std::endl; if(has_cells_without_flow_directions) std::cerr<<"W \033[91mNot all cells had defined flow directions! This implies that there will be digital dams!\033[39m"<<std::endl; /////////////////////// //Find those cells which have no dependencies. These are the places to start //the flow accumulation calculation. std::cerr<<"p Locating source cells..."<<std::endl; progress.start( flowdirs.size() ); for(int y=0;y<flowdirs.height();y++){ progress.update( y*flowdirs.width() ); for(int x=0;x<flowdirs.width();x++) if(flowdirs(x,y)==flowdirs.noData()) continue; else if(flowdirs(x,y)==NO_FLOW) continue; else if(dependency(x,y)==0) sources.emplace(x,y); } std::cerr<<"t Source cells located in = "<<progress.stop()<<" s"<<std::endl; /////////////////////// //Calculate the flow accumulation by "pouring" a cell's flow accumulation //value into the cells below it, as indicated by the D-infinite flow routing //method. std::cerr<<"p Calculating up-slope areas..."<<std::endl; progress.start( flowdirs.numDataCells() ); long int ccount=0; while(sources.size()>0){ auto c = sources.front(); sources.pop(); progress.update(ccount++); if(flowdirs.isNoData(c.x,c.y)) //TODO: This line shouldn't be necessary since NoData's do not get added below continue; area(c.x,c.y)+=1; if(flowdirs(c.x,c.y)==NO_FLOW) continue; int n_high,n_low,nhx,nhy,nlx,nly; where_do_i_flow(flowdirs(c.x,c.y),n_high,n_low); nhx = c.x+dinf_dx[n_high]; nhy = c.y+dinf_dy[n_high]; float phigh,plow; area_proportion(flowdirs(c.x,c.y), n_high, n_low, phigh, plow); if(flowdirs.inGrid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.noData()) area(nhx,nhy)+=area(c.x,c.y)*phigh; if(n_low!=-1){ nlx = c.x+dinf_dx[n_low]; nly = c.y+dinf_dy[n_low]; if(flowdirs.inGrid(nlx,nly) && flowdirs(nlx,nly)!=flowdirs.noData()){ area(nlx,nly)+=area(c.x,c.y)*plow; if((--dependency(nlx,nly))==0) sources.emplace(nlx,nly); } } if( flowdirs.inGrid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.noData() && (--dependency(nhx,nhy))==0) sources.emplace(nhx,nhy); } std::cerr<<"p Succeeded in = "<<progress.stop()<<" s"<<std::endl; }
void Garbrecht_FindFlats(const Array2D<d8_flowdir_t> &flowdirs, garbrecht_flat_type &flats){ for(int x=0;x<flowdirs.width();++x) for(int y=0;y<flowdirs.height();++y) if(flowdirs(x,y)==NO_FLOW) flats.emplace_back(x,y); }
void Zhou2015Labels( Array2D<elev_t> &dem, Array2D<label_t> &labels, std::vector<std::map<label_t, elev_t> > &my_graph, uint8_t edge, bool flipH, bool flipV ){ std::queue<GridCellZ<elev_t> > traceQueue; std::queue<GridCellZ<elev_t> > depressionQue; label_t current_label = 2; labels.setAll(0); GridCellZ_pq<elev_t> priorityQueue; for(int32_t x=0;x<dem.width();x++){ const int height = dem.height()-1; priorityQueue.emplace(x,0, dem(x,0 )); priorityQueue.emplace(x,height,dem(x,height)); } for(int32_t y=1;y<dem.height()-1;y++){ const int width = dem.width()-1; priorityQueue.emplace(0, y,dem(0, y)); priorityQueue.emplace(width,y,dem(width,y)); } while (!priorityQueue.empty()){ GridCellZ<elev_t> c = priorityQueue.top(); priorityQueue.pop(); auto my_label = labels(c.x,c.y) = GetNewLabelZhou(c.x,c.y,current_label,edge,dem,labels); for(int n=1;n<=8;n++){ int nx = c.x+dx[n]; int ny = c.y+dy[n]; if (!dem.inGrid(nx,ny)) continue; WatershedsMeet(my_label,labels(nx,ny),dem(c.x,c.y),dem(nx,ny),my_graph); if(labels(nx,ny)!=0) continue; labels(nx,ny) = labels(c.x,c.y); if(dem(nx,ny)<=c.z){ //Depression cell dem(nx,ny) = c.z; depressionQue.emplace(nx,ny,c.z); ProcessPit_onepass(dem,labels,depressionQue,traceQueue,priorityQueue,my_graph); } else { //Slope cell traceQueue.emplace(nx,ny,dem(nx,ny)); } ProcessTraceQue_onepass(dem,labels,traceQueue,priorityQueue,my_graph); } } //Connect the DEM's outside edges to Special Watershed 1. This requires //knowing whether the tile has been flipped toe snure that we connect the //correct edges. if( ((edge & GRID_TOP) && !flipV) || ((edge & GRID_BOTTOM) && flipV) ) for(int32_t x=0;x<labels.width();x++) WatershedsMeet(labels(x,0),(label_t)1,dem(x,0),dem(x,0),my_graph); if( ((edge & GRID_BOTTOM) && !flipV) || ((edge & GRID_TOP) && flipV) ){ int bottom_row = labels.height()-1; for(int32_t x=0;x<labels.width();x++) WatershedsMeet(labels(x,bottom_row),(label_t)1,dem(x,bottom_row),dem(x,bottom_row),my_graph); } if( ((edge & GRID_LEFT) && !flipH) || ((edge & GRID_RIGHT) && flipH) ) for(int32_t y=0;y<labels.height();y++) WatershedsMeet(labels(0,y),(label_t)1,dem(0,y),dem(0,y),my_graph); if( ((edge & GRID_RIGHT) && !flipH) || ((edge & GRID_LEFT) && flipH) ){ int right_col = labels.width()-1; for(int32_t y=0;y<labels.height();y++) WatershedsMeet(labels(right_col,y),(label_t)1,dem(right_col,y),dem(right_col,y),my_graph); } my_graph.resize(current_label); }
void FM_Freeman( const Array2D<E> &elevations, Array3D<float> &props, const double xparam ){ RDLOG_ALG_NAME<<"Freeman (1991) Flow Accumulation (aka MFD, MD8)"; RDLOG_CITATION<<"Freeman, T.G., 1991. Calculating catchment area with divergent flow based on a regular grid. Computers & Geosciences 17, 413–422."; RDLOG_CONFIG<<"p = "<<xparam; props.setAll(NO_FLOW_GEN); props.setNoData(NO_DATA_GEN); ProgressBar progress; progress.start(elevations.size()); #pragma omp parallel for collapse(2) for(int y=0;y<elevations.height();y++) for(int x=0;x<elevations.width();x++){ ++progress; if(elevations.isNoData(x,y)){ props(x,y,0) = NO_DATA_GEN; continue; } if(elevations.isEdgeCell(x,y)) continue; const E e = elevations(x,y); double C = 0; for(int n=1;n<=8;n++){ const int nx = x+dx[n]; const int ny = y+dy[n]; if(!elevations.inGrid(nx,ny)) continue; if(elevations.isNoData(nx,ny)) //TODO: Don't I want water to drain this way? continue; const E ne = elevations(nx,ny); if(ne<e){ const double rise = e-ne; const double run = dr[n]; const double grad = rise/run; const auto cval = std::pow(grad,xparam); props(x,y,n) = cval; C += cval; } } if(C>0){ props(x,y,0) = HAS_FLOW_GEN; C = 1/C; //TODO for(int n=1;n<=8;n++){ auto &this_por = props(x,y,n); if(this_por>0) this_por *= C; else this_por = 0; } } } progress.stop(); }