Example #1
0
void ProcessPit_onepass(Array2D<elev_t> &dem, Array2D<label_t> &labels, std::queue<GridCellZ<elev_t> > &depressionQue, std::queue<GridCellZ<elev_t> > &traceQueue, GridCellZ_pq<elev_t> &priorityQueue, std::vector<std::map<label_t, elev_t> > &my_graph){
  while (!depressionQue.empty()){
    GridCellZ<elev_t> c = depressionQue.front();
    depressionQue.pop();

    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(labels(c.x,c.y),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) { //Slope cell
        traceQueue.emplace(nx,ny,dem(nx,ny));
      } else {                //Depression cell
        dem(nx,ny) = c.z;
        depressionQue.emplace(nx,ny,c.z);
      }
    }
  }
}
Example #2
0
void ProcessTraceQue_onepass(Array2D<elev_t> &dem, Array2D<label_t> &labels, std::queue<GridCellZ<elev_t> > &traceQueue, GridCellZ_pq<elev_t> &priorityQueue, std::vector<std::map<label_t, elev_t> > &my_graph){
  while (!traceQueue.empty()){
    GridCellZ<elev_t> c = traceQueue.front();
    traceQueue.pop();

    bool bInPQ = false;
    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(labels(c.x,c.y),labels(nx,ny),dem(c.x,c.y),dem(nx,ny),my_graph);

      if(labels(nx,ny)!=0)
        continue;    
      
      //The neighbour is unprocessed and higher than the central cell
      if(c.z<dem(nx,ny)){
        traceQueue.emplace(nx,ny,dem(nx,ny));
        labels(nx,ny) = labels(c.x,c.y);
        continue;
      }

      //Decide  whether (nx, ny) is a true border cell
      if (!bInPQ) {
        bool isBoundary = true;
        for(int nn=1;nn<=8;nn++){
          int nnx = nx+dx[n];
          int nny = ny+dy[n];
          if(!dem.inGrid(nnx,nny))
            continue;
          if (labels(nnx,nny)!=0 && dem(nnx,nny)<dem(nx,ny)){
            isBoundary = false;
            break;
          }
        }
        if(isBoundary){
          priorityQueue.push(c);
          bInPQ = true;
        }
      }
    }
  }
}
Example #3
0
static inline TA_Setup_Vars TerrainSetup(const Array2D<T> &elevations, const int x, const int y, const float zscale){
  TA_Setup_Vars tsv;
  tsv.a=tsv.b=tsv.c=tsv.d=tsv.e=tsv.f=tsv.g=tsv.h=tsv.i=elevations(x,y);
  if(elevations.inGrid(x-1,y-1) && elevations(x-1,y-1)!=elevations.noData()) tsv.a = elevations(x-1,y-1);
  if(elevations.inGrid(x-1,y  ) && elevations(x-1,y  )!=elevations.noData()) tsv.d = elevations(x-1,y  );
  if(elevations.inGrid(x-1,y+1) && elevations(x-1,y+1)!=elevations.noData()) tsv.g = elevations(x-1,y+1);
  if(elevations.inGrid(x  ,y-1) && elevations(x,  y-1)!=elevations.noData()) tsv.b = elevations(x,  y-1);
  if(elevations.inGrid(x  ,y+1) && elevations(x,  y+1)!=elevations.noData()) tsv.h = elevations(x,  y+1);
  if(elevations.inGrid(x+1,y-1) && elevations(x+1,y-1)!=elevations.noData()) tsv.c = elevations(x+1,y-1);
  if(elevations.inGrid(x+1,y  ) && elevations(x+1,y  )!=elevations.noData()) tsv.f = elevations(x+1,y  );
  if(elevations.inGrid(x+1,y+1) && elevations(x+1,y+1)!=elevations.noData()) tsv.i = elevations(x+1,y+1);

  tsv.a *= zscale;
  tsv.b *= zscale;
  tsv.c *= zscale;
  tsv.d *= zscale;
  tsv.e *= zscale;
  tsv.f *= zscale;
  tsv.g *= zscale;
  tsv.h *= zscale;
  tsv.i *= zscale;

  return tsv;
}
Example #4
0
label_t GetNewLabelZhou(
  int x,
  int y,
  label_t &current_label,
  uint8_t edge,
  const Array2D<elev_t> &dem,
  const Array2D<label_t> &labels
){
  if(labels(x,y)!=0)
    return labels(x,y);

  for(int n=1;n<=8;n++){
    int nx = x+dx[n];
    int ny = y+dy[n];
    if(!dem.inGrid(nx,ny))
      continue;
    if(labels(nx,ny)!=0 && dem(nx,ny)<=dem(x,y))
      return labels(nx,ny);
  }

  return current_label++;
}
Example #5
0
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);
}
Example #6
0
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;
}
Example #7
0
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();
}