void original_priority_flood(Array2D<elev_t> &elevations) { grid_cellz_pq<elev_t> open; unsigned long processed_cells = 0; unsigned long pitc = 0; //ProgressBar progress; //std::cerr << "\n###Barnes Flood" << std::endl; //std::cerr << "Setting up boolean flood array matrix..." << std::flush; Array2D<int8_t> closed(elevations.viewWidth(), elevations.viewHeight(), false); //std::cerr << "succeeded." << std::endl; //std::cerr << "The priority queue will require approximately " // << (elevations.viewWidth() * 2 + elevations.viewHeight() * 2)*((long)sizeof(grid_cellz<elev_t>)) / 1024 / 1024 // << "MB of RAM." // << std::endl; //std::cerr << "Adding cells to the priority queue..." << std::endl; for (int x = 0; x < elevations.viewWidth(); x++) { open.push_cell(x, 0, elevations(x, 0)); open.push_cell(x, elevations.viewHeight() - 1, elevations(x, elevations.viewHeight() - 1)); closed(x, 0) = true; closed(x, elevations.viewHeight() - 1) = true; } for (int y = 1; y < elevations.viewHeight() - 1; y++) { open.push_cell(0, y, elevations(0, y)); open.push_cell(elevations.viewWidth() - 1, y, elevations(elevations.viewWidth() - 1, y)); closed(0, y) = true; closed(elevations.viewWidth() - 1, y) = true; } //std::cerr << "succeeded." << std::endl; //std::cerr << "%%Performing the original Priority Flood..." << std::endl; //progress.start( elevations.viewWidth()*elevations.viewHeight() ); while (open.size() > 0) { grid_cellz<elev_t> c = open.top(); open.pop(); processed_cells++; for (int n = 1; n <= 8; n++) { int nx = c.x + dx[n]; int ny = c.y + dy[n]; if (!elevations.in_grid(nx, ny)) continue; if (closed(nx, ny)) continue; closed(nx, ny) = true; if (elevations(nx, ny) < elevations(c.x, c.y)) ++pitc; elevations(nx, ny) = std::max(elevations(nx, ny), elevations(c.x, c.y)); open.push_cell(nx, ny, elevations(nx, ny)); } //progress.update(processed_cells); } //std::cerr<<"\t\033[96msucceeded in "<<progress.stop()<<"s.\033[39m"<<std::endl; //std::cerr<<processed_cells<<" cells processed. "<<pitc<<" in pits."<<std::endl; }
void priority_flood_watersheds( Array2D<elev_t> &elevations, Array2D<int32_t> &labels, bool alter_elevations ) { grid_cellz_pq<elev_t> open; std::queue<grid_cellz<elev_t> > pit; unsigned long processed_cells = 0; unsigned long pitc = 0, openc = 0; int clabel = 1; //TODO: Thought this was more clear than zero in the results. ProgressBar progress; std::cerr << "\n###Priority-Flood+Watershed Labels" << std::endl; std::cerr << "Setting up boolean flood array matrix..." << std::flush; Array2D<int8_t> closed(elevations.viewWidth(), elevations.viewHeight(), false); std::cerr << "succeeded." << std::endl; std::cerr << "Setting up watershed label matrix..." << std::flush; labels.resize(elevations.viewWidth(), elevations.viewHeight(), -1); labels.setNoData(-1); std::cerr << "succeeded." << std::endl; std::cerr << "The priority queue will require approximately " << (elevations.viewWidth() * 2 + elevations.viewHeight() * 2)*((long)sizeof(grid_cellz<elev_t>)) / 1024 / 1024 << "MB of RAM." << std::endl; std::cerr << "Adding cells to the priority queue..." << std::endl; for (int x = 0; x < elevations.viewWidth(); x++) { open.push_cell(x, 0, elevations(x, 0)); open.push_cell(x, elevations.viewHeight() - 1, elevations(x, elevations.viewHeight() - 1)); closed(x, 0) = true; closed(x, elevations.viewHeight() - 1) = true; } for (int y = 1; y < elevations.viewHeight() - 1; y++) { open.push_cell(0, y, elevations(0, y)); open.push_cell(elevations.viewWidth() - 1, y, elevations(elevations.viewWidth() - 1, y)); closed(0, y) = true; closed(elevations.viewWidth() - 1, y) = true; } std::cerr << "succeeded." << std::endl; std::cerr << "%%Performing Priority-Flood+Watershed Labels..." << std::endl; progress.start(elevations.viewWidth()*elevations.viewHeight()); while (open.size() > 0 || pit.size()>0) { grid_cellz<elev_t> c; if (pit.size() > 0) { c = pit.front(); pit.pop(); pitc++; } else { c = open.top(); open.pop(); openc++; } processed_cells++; //Since all interior cells will be flowing into a cell which has already //been processed, the following line identifies only the edge cells of the //DEM. Each edge cell seeds its own watershed/basin. The result of this will //be many small watersheds/basins around the edge of the DEM. if (labels(c.x, c.y) == labels.noData() && elevations(c.x, c.y) != elevations.noData()) //Implies a cell without a label which borders the edge of the DEM or a region of no_data labels(c.x, c.y) = clabel++; for (int n = 1; n <= 8; n++) { int nx = c.x + dx[n]; int ny = c.y + dy[n]; if (!elevations.in_grid(nx, ny)) continue; if (closed(nx, ny)) continue; //Since the neighbouring cell is not closed, its flow is directed to this //cell. Therefore, it is part of the same watershed/basin as this cell. labels(nx, ny) = labels(c.x, c.y); closed(nx, ny) = true; if (elevations(nx, ny) <= c.z) { if (alter_elevations) elevations(nx, ny) = c.z; pit.push(grid_cellz<elev_t>(nx, ny, c.z)); } else open.push(grid_cellz<elev_t>(nx, ny, elevations(nx, ny))); } progress.update(processed_cells); } std::cerr << "\t\033[96msucceeded in " << progress.stop() << "s.\033[39m" << std::endl; std::cerr << processed_cells << " cells processed. " << pitc << " in pits, " << openc << " not in pits." << std::endl; }
void pit_mask(const Array2D<elev_t> &elevations, Array2D<int32_t> &pit_mask) { grid_cellz_pq<elev_t> open; std::queue<grid_cellz<elev_t> > pit; unsigned long processed_cells = 0; unsigned long pitc = 0; ProgressBar progress; std::cerr << "\n###Pit Mask" << std::endl; std::cerr << "Setting up boolean flood array matrix..." << std::flush; Array2D<int8_t> closed(elevations.viewWidth(), elevations.viewHeight(), false); std::cerr << "succeeded." << std::endl; std::cerr << "Setting up the pit mask matrix..." << std::endl; pit_mask.resize(elevations.viewWidth(), elevations.viewHeight()); pit_mask.setNoData(3); std::cerr << "succeeded." << std::endl; std::cerr << "The priority queue will require approximately " << (elevations.viewWidth() * 2 + elevations.viewHeight() * 2)*((long)sizeof(grid_cellz<elev_t>)) / 1024 / 1024 << "MB of RAM." << std::endl; std::cerr << "Adding cells to the priority queue..." << std::flush; for (int x = 0; x < elevations.viewWidth(); x++) { open.push_cell(x, 0, elevations(x, 0)); open.push_cell(x, elevations.viewHeight() - 1, elevations(x, elevations.viewHeight() - 1)); closed(x, 0) = true; closed(x, elevations.viewHeight() - 1) = true; } for (int y = 1; y < elevations.viewHeight() - 1; y++) { open.push_cell(0, y, elevations(0, y)); open.push_cell(elevations.viewWidth() - 1, y, elevations(elevations.viewWidth() - 1, y)); closed(0, y) = true; closed(elevations.viewWidth() - 1, y) = true; } std::cerr << "succeeded." << std::endl; std::cerr << "%%Performing the pit mask..." << std::endl; progress.start(elevations.viewWidth()*elevations.viewHeight()); while (open.size() > 0 || pit.size()>0) { grid_cellz<elev_t> c; if (pit.size() > 0) { c = pit.front(); pit.pop(); } else { c = open.top(); open.pop(); } processed_cells++; for (int n = 1; n <= 8; n++) { int nx = c.x + dx[n]; int ny = c.y + dy[n]; if (!elevations.in_grid(nx, ny)) continue; if (closed(nx, ny)) continue; closed(nx, ny) = true; if (elevations(nx, ny) <= c.z) { if (elevations(nx, ny) < c.z) pit_mask(nx, ny) = 1; pit.push(grid_cellz<elev_t>(nx, ny, c.z)); } else { pit_mask(nx, ny) = 0; open.push_cell(nx, ny, elevations(nx, ny)); } } if (elevations(c.x, c.y) == elevations.noData()) pit_mask(c.x, c.y) = pit_mask.noData(); progress.update(processed_cells); } std::cerr << "\t\033[96msucceeded in " << progress.stop() << "s.\033[39m" << std::endl; std::cerr << processed_cells << " cells processed. " << pitc << " in pits." << std::endl; }
void priority_flood_flowdirs(const Array2D<elev_t> &elevations, Array2D<int8_t> &flowdirs) { grid_cellzk_pq<elev_t> open; unsigned long processed_cells = 0; ProgressBar progress; std::cerr << "\n###Priority-Flood+Flow Directions" << std::endl; std::cerr << "Setting up boolean flood array matrix..." << std::flush; Array2D<int8_t> closed(elevations.viewWidth(), elevations.viewHeight(), false); std::cerr << "succeeded." << std::endl; std::cerr << "Setting up the flowdirs matrix..." << std::flush; flowdirs.resize(elevations.viewWidth(), elevations.viewHeight()); flowdirs.setNoData(NO_FLOW); std::cerr << "succeeded." << std::endl; std::cerr << "The priority queue will require approximately " << (elevations.viewWidth() * 2 + elevations.viewHeight() * 2)*((long)sizeof(grid_cellz<elev_t>)) / 1024 / 1024 << "MB of RAM." << std::endl; std::cerr << "Adding cells to the priority queue..." << std::endl; for (int x = 0; x < elevations.viewWidth(); x++) { open.push_cell(x, 0, elevations(x, 0)); open.push_cell(x, elevations.viewHeight() - 1, elevations(x, elevations.viewHeight() - 1)); flowdirs(x, 0) = 3; flowdirs(x, elevations.viewHeight() - 1) = 7; closed(x, 0) = true; closed(x, elevations.viewHeight() - 1) = true; } for (int y = 1; y < elevations.viewHeight() - 1; y++) { open.push_cell(0, y, elevations(0, y)); open.push_cell(elevations.viewWidth() - 1, y, elevations(elevations.viewWidth() - 1, y)); flowdirs(0, y) = 1; flowdirs(elevations.viewWidth() - 1, y) = 5; closed(0, y) = true; closed(elevations.viewWidth() - 1, y) = true; } std::cerr << "succeeded." << std::endl; flowdirs(0, 0) = 2; flowdirs(flowdirs.viewWidth() - 1, 0) = 4; flowdirs(0, flowdirs.viewHeight() - 1) = 8; flowdirs(flowdirs.viewWidth() - 1, flowdirs.viewHeight() - 1) = 6; const int d8_order[9] = { 0,1,3,5,7,2,4,6,8 }; std::cerr << "%%Performing Priority-Flood+Flow Directions..." << std::endl; progress.start(elevations.viewWidth()*elevations.viewHeight()); while (open.size() > 0) { grid_cellz<elev_t> c = open.top(); open.pop(); processed_cells++; for (int no = 1; no <= 8; no++) { int n = d8_order[no]; int nx = c.x + dx[n]; int ny = c.y + dy[n]; if (!elevations.in_grid(nx, ny)) continue; if (closed(nx, ny)) continue; closed(nx, ny) = true; if (elevations(nx, ny) == elevations.noData()) flowdirs(nx, ny) = flowdirs.noData(); else flowdirs(nx, ny) = inverse_flow[n]; open.push_cell(nx, ny, elevations(nx, ny)); } progress.update(processed_cells); } std::cerr << "\t\033[96msucceeded in " << progress.stop() << "s.\033[39m" << std::endl; std::cerr << processed_cells << " cells processed." << std::endl; }
void priority_flood_epsilon(Array2D<elev_t> &elevations) { grid_cellz_pq<elev_t> open; std::queue<grid_cellz<elev_t> > pit; ProgressBar progress; unsigned long processed_cells = 0; unsigned long pitc = 0; auto PitTop = elevations.noData(); int false_pit_cells = 0; std::cerr << "\n###Priority-Flood+Epsilon" << std::endl; std::cerr << "Setting up boolean flood array matrix..." << std::flush; Array2D<int8_t> closed(elevations.viewWidth(), elevations.viewHeight(), false); std::cerr << "succeeded." << std::endl; std::cerr << "The priority queue will require approximately " << (elevations.viewWidth() * 2 + elevations.viewHeight() * 2)*((long)sizeof(grid_cellz<elev_t>)) / 1024 / 1024 << "MB of RAM." << std::endl; std::cerr << "Adding cells to the priority queue..." << std::flush; for (int x = 0; x < elevations.viewWidth(); x++) { open.push_cell(x, 0, elevations(x, 0)); open.push_cell(x, elevations.viewHeight() - 1, elevations(x, elevations.viewHeight() - 1)); closed(x, 0) = true; closed(x, elevations.viewHeight() - 1) = true; } for (int y = 1; y < elevations.viewHeight() - 1; y++) { open.push_cell(0, y, elevations(0, y)); open.push_cell(elevations.viewWidth() - 1, y, elevations(elevations.viewWidth() - 1, y)); closed(0, y) = true; closed(elevations.viewWidth() - 1, y) = true; } std::cerr << "succeeded." << std::endl; std::cerr << "%%Performing Priority-Flood+Epsilon..." << std::endl; progress.start(elevations.viewWidth()*elevations.viewHeight()); while (open.size() > 0 || pit.size()>0) { grid_cellz<elev_t> c; if (pit.size() > 0 && open.size() > 0 && open.top().z == pit.front().z) { c = open.top(); open.pop(); PitTop = elevations.noData(); } else if (pit.size() > 0) { c = pit.front(); pit.pop(); if (PitTop == elevations.noData()) PitTop = elevations(c.x, c.y); } else { c = open.top(); open.pop(); PitTop = elevations.noData(); } processed_cells++; for (int n = 1; n <= 8; n++) { int nx = c.x + dx[n]; int ny = c.y + dy[n]; if (!elevations.in_grid(nx, ny)) continue; if (closed(nx, ny)) continue; closed(nx, ny) = true; if (elevations(nx, ny) == elevations.noData()) pit.push(grid_cellz<elev_t>(nx, ny, elevations.noData())); else if (elevations(nx, ny) <= nextafterf(c.z, std::numeric_limits<float>::infinity())) { if (PitTop != elevations.noData() && PitTop < elevations(nx, ny) && nextafterf(c.z, std::numeric_limits<float>::infinity()) >= elevations(nx, ny)) ++false_pit_cells; ++pitc; elevations(nx, ny) = nextafterf(c.z, std::numeric_limits<float>::infinity()); pit.push(grid_cellz<elev_t>(nx, ny, elevations(nx, ny))); } else open.push_cell(nx, ny, elevations(nx, ny)); } progress.update(processed_cells); } std::cerr << "\t\033[96msucceeded in " << progress.stop() << "s.\033[39m" << std::endl; std::cerr << processed_cells << " cells processed. " << pitc << " in pits." << std::endl; if (false_pit_cells) std::cerr << "\033[91mIn assigning negligible gradients to depressions, some depressions rose above the surrounding cells. This implies that a larger storage type should be used. The problem occured for " << false_pit_cells << " of " << elevations.numDataCells() << std::endl; }