示例#1
0
void d8_flow_directions(
  const array2d<T> &elevations,
  array2d<U> &flowdirs
){
  ProgressBar progress;

  diagnostic("Setting up the flow directions matrix...");
  flowdirs.copyprops(elevations);
  flowdirs.init(NO_FLOW);
  flowdirs.no_data=d8_NO_DATA;
  diagnostic("succeeded.\n");

  diagnostic("%%Calculating D8 flow directions...\n");
  progress.start( elevations.width()*elevations.height() );
  #pragma omp parallel for
  for(int x=0;x<elevations.width();x++){
    progress.update( x*elevations.height() );
    for(int y=0;y<elevations.height();y++)
      if(elevations(x,y)==elevations.no_data)
        flowdirs(x,y)=flowdirs.no_data;
      else
        flowdirs(x,y)=d8_FlowDir(elevations,x,y);
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
}
/**
  @brief  Writes an arrow representation of a 2D D8 flow direction array
  @author Richard Barnes

  @param[in] &filename     Name of file to write to
  @param[in] &elevations   2D array of D8 flow directions

  @returns 0 upon success
*/
int write_arrows(const char filename[], const char_2d &flowdirs){
  std::locale::global(std::locale(""));
  std::wofstream fout;
  Timer write_time;
  ProgressBar progress;

  write_time.start();

  diagnostic_arg("Opening arrow output file \"%s\"...",filename);
  fout.open(filename);
  if(!fout.is_open()){
    diagnostic("failed!\n");
    exit(-1);  //TODO: Need to make this safer! Don't just close after all that work!
  }
  diagnostic("succeeded.\n");

  diagnostic("%%Writing arrows...\n");
  progress.start( flowdirs.width()*flowdirs.height() );
  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.no_data)  //TODO: Crude way of detecting chars and bools
        fout<<L" ";
      else if (flowdirs(x,y)==NO_FLOW)
        fout<<fd[0];
      else
        fout<<fd[flowdirs(x,y)];
      fout<<L" ";
    }
    fout<<std::endl;
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  fout.close();

  write_time.stop();
  diagnostic_arg("Write time was: %lf\n", write_time.accumulated());

  return 0;
}
示例#3
0
void d8_flats_alter_dem(
  const int_2d &flat_mask,
  const int_2d &labels,
  array2d<U> &elevations
){
  ProgressBar progress;

  diagnostic("%%Calculating D8 flow directions using flat mask...\n");
  progress.start( flat_mask.width()*flat_mask.height() );
  #pragma omp parallel for
  for(int x=1;x<flat_mask.width()-1;x++){
    progress.update( x*flat_mask.height() );
    for(int y=1;y<flat_mask.height()-1;y++){
      if(labels(x,y)==0)
        continue;

      bool higher[9];
      for(int n=1;n<=8;++n)
        higher[n]=elevations(x,y)>elevations(x+dx[n],y+dy[n]);
      //TODO: nextafterf is the floating point version; should use an
      //overloaded version instead to be able to handle both double and float
      for(int i=0;i<flat_mask(x,y);++i)
        elevations(x,y)=nextafterf(elevations(x,y),std::numeric_limits<U>::infinity());
      for(int n=1;n<=8;++n){
        int nx=x+dx[n];
        int ny=y+dy[n];      
        if(labels(nx,ny)==labels(x,y))
          continue;
        if(elevations(x,y)<elevations(nx,ny))
          continue;
        if(!higher[n])
          diagnostic_arg("Attempting to raise (%d,%d) resulted in an invalid alteration of the DEM!\n",x,y);
      }
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
}
示例#4
0
void d8_flow_flats(
  const int_2d &flat_mask,
  const int_2d &groups,
  array2d<U> &flowdirs
){
  ProgressBar progress;

  diagnostic("%%Calculating D8 flow directions using flat mask...\n");
  progress.start( flat_mask.width()*flat_mask.height() );
  #pragma omp parallel for
  for(int x=1;x<flat_mask.width()-1;x++){
    progress.update( x*flat_mask.height() );
    for(int y=1;y<flat_mask.height()-1;y++)
      if(flat_mask(x,y)==flat_mask.no_data)
        continue;
      else if (flowdirs(x,y)==NO_FLOW)
        flowdirs(x,y)=d8_masked_FlowDir(flat_mask,groups,x,y);
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
}
/**
  @brief  Reads an ArcGrid ASCII file
  @author Richard Barnes

  @param[in]  &filename     Name of ArcGrid ASCII file to read
  @param[out] &elevations   DEM object containing contents of file

  @returns 0 upon success
*/
int load_ascii_data(const char filename[], float_2d &elevations){
  FILE *fin;
  long long file_size;
  int rows,columns;
  Timer load_time;
  ProgressBar progress;

  load_time.start();

  errno=0;
  diagnostic_arg("Opening input ASCII-DEM file \"%s\"...",filename);
  fin=fopen(filename,"r");
  if(fin==NULL){
    diagnostic_arg("failed with error %d: \"%s\"!\n",errno,strerror(errno));
    exit(-1);
  }
  diagnostic("succeeded.\n");

  diagnostic("Calculating file size...");
  if(fseek(fin,-1,SEEK_END)!=0){
    diagnostic("failed! (Couldn't jump to end of file.)\n");
    exit(-1);
  }
  if((file_size=ftell(fin))==-1){
    diagnostic("failed! (Couldn't determine file size.)\n");
    exit(-1);
  }
  if(fseek(fin,0,SEEK_SET)!=0){
    diagnostic("failed! (Couldn't jump back to beginning of file.)\n");
    exit(-1);
  }
  diagnostic("succeeded.\n");

//  posix_fadvise(fileno(fin),0,0,POSIX_FADV_SEQUENTIAL);

  diagnostic("Reading DEM header...");
  if(fscanf(fin,"ncols %d nrows %d xllcorner %lf yllcorner %lf cellsize %lf NODATA_value %f",&columns, &rows, &elevations.xllcorner, &elevations.yllcorner, &elevations.cellsize, &elevations.no_data)!=6){
    diagnostic("failed!\n");
    exit(-1);
  }
  diagnostic("succeeded.\n");

  diagnostic_arg("The loaded DEM will require approximately %ldMB of RAM.\n",columns*rows*((long)sizeof(float))/1024/1024);

  diagnostic("Resizing elevation matrix...");  //TODO: Consider abstracting this block
  elevations.resize(columns,rows);
  diagnostic("succeeded.\n");

  diagnostic("%%Reading elevation matrix...\n");
  progress.start(file_size);
  float temp;
  elevations.data_cells=0;
  for(int y=0;y<rows;y++){
    progress.update(ftell(fin)); //Todo: Check to see if ftell fails here?
    for(int x=0;x<columns;x++){
      if (fscanf(fin,"%f", &temp)!=1){
        diagnostic("\n\tFailed! (Couldn't read or convert a value!)\n");
        exit(-1);
      }
      elevations(x,y)=temp;
      if(temp!=elevations.no_data)
        elevations.data_cells++;
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  fclose(fin);

  diagnostic_arg(
    "Read %ld cells, of which %ld contained data (%ld%%).\n",
    elevations.width()*elevations.height(), elevations.data_cells,
    elevations.data_cells*100/elevations.width()/elevations.height()
  );

  load_time.stop();
  diagnostic_arg("Read time was: %lfs\n", load_time.accumulated());

  return 0;
}
示例#6
0
void d8_upslope_cells(
  int x0, int y0, int x1, int y1,
  const array2d<T> &flowdirs,array2d<U> &upslope_cells
){
  diagnostic("Setting up the upslope_cells matrix...");
  upslope_cells.copyprops(flowdirs);
  upslope_cells.init(d8_NO_DATA);
  upslope_cells.no_data=d8_NO_DATA;
  diagnostic("succeeded.\n");
  ProgressBar progress;

  std::queue<grid_cell> expansion;

  if(x0>x1){
    std::swap(x0,x1);
    std::swap(y0,y1);
  }

  //Modified Bresenham Line-Drawing Algorithm
  int deltax=x1-x0;
  int deltay=y1-y0;
  float error=0;
  float deltaerr=(float)deltay/(float)deltax;
  if (deltaerr<0)
    deltaerr=-deltaerr;
  diagnostic_arg("Line slope is %f\n",deltaerr);
  int y=y0;
  for(int x=x0;x<=x1;x++){
    expansion.push(grid_cell(x,y));
    upslope_cells(x,y)=2;
    error+=deltaerr;
    if (error>=0.5) {
      expansion.push(grid_cell(x+1,y));
      upslope_cells(x+1,y)=2;
      y+=sgn(deltay);
      error-=1;
    }
  }

  progress.start(flowdirs.data_cells);
  long int ccount=0;
  while(expansion.size()>0){
    grid_cell c=expansion.front();
    expansion.pop();

    progress.update(ccount++);

    for(int n=1;n<=8;n++)
      if(!flowdirs.in_grid(c.x+dx[n],c.y+dy[n]))
        continue;
      else if(flowdirs(c.x+dx[n],c.y+dy[n])==NO_FLOW)
        continue;
      else if(flowdirs(c.x+dx[n],c.y+dy[n])==flowdirs.no_data)
        continue;
      else if(upslope_cells(c.x+dx[n],c.y+dy[n])==upslope_cells.no_data && n==inverse_flow[flowdirs(c.x+dx[n],c.y+dy[n])]){
        expansion.push(grid_cell(c.x+dx[n],c.y+dy[n]));
        upslope_cells(c.x+dx[n],c.y+dy[n])=1;
      }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
  diagnostic_arg("Found %ld up-slope cells.\n",ccount);
}
示例#7
0
void d8_upslope_area(const array2d<T> &flowdirs, array2d<U> &area){
  char_2d dependency;
  std::queue<grid_cell> sources;
  ProgressBar progress;

  diagnostic("\n###D8 Upslope Area\n");

  diagnostic_arg(
    "The sources queue will require at most approximately %ldMB of RAM.\n",
    flowdirs.width()*flowdirs.height()*((long)sizeof(grid_cell))/1024/1024
  );

  diagnostic("Resizing dependency matrix...");
  dependency.copyprops(flowdirs);
  diagnostic("succeeded.\n");

  diagnostic("Setting up the area matrix...");
  area.copyprops(flowdirs);
  area.init(0);
  area.no_data=d8_NO_DATA;
  diagnostic("succeeded.\n");

  diagnostic("%%Calculating dependency matrix & setting no_data cells...\n");
  progress.start( flowdirs.width()*flowdirs.height() );
  #pragma omp parallel for
  for(int x=0;x<flowdirs.width();x++){
    progress.update( x*flowdirs.height() );
    for(int y=0;y<flowdirs.height();y++){
      dependency(x,y)=0;
      if(flowdirs(x,y)==flowdirs.no_data){
        area(x,y)=area.no_data;
        continue;
      }
      for(int n=1;n<=8;n++)
        if(!flowdirs.in_grid(x+dx[n],y+dy[n]))
          continue;
        else if(flowdirs(x+dx[n],y+dy[n])==NO_FLOW)
          continue;
        else if(flowdirs(x+dx[n],y+dy[n])==flowdirs.no_data)
          continue;
        else if(n==inverse_flow[(int)flowdirs(x+dx[n],y+dy[n])])
          ++dependency(x,y);
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  diagnostic("%%Locating source cells...\n");
  progress.start( flowdirs.width()*flowdirs.height() );
  for(int x=0;x<flowdirs.width();x++){
    progress.update( x*flowdirs.height() );
    for(int y=0;y<flowdirs.height();y++)
      if(flowdirs(x,y)==flowdirs.no_data)
        continue;
      else if(dependency(x,y)==0)
        sources.push(grid_cell(x,y));
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  diagnostic("%%Calculating up-slope areas...\n");
  progress.start(flowdirs.data_cells);
  long int ccount=0;
  while(sources.size()>0){
    grid_cell c=sources.front();
    sources.pop();

    ccount++;
    progress.update(ccount);

    area(c.x,c.y)+=1;

    if(flowdirs(c.x,c.y)==NO_FLOW)
      continue;

    int nx=c.x+dx[(int)flowdirs(c.x,c.y)];
    int ny=c.y+dy[(int)flowdirs(c.x,c.y)];
    if(flowdirs.in_grid(nx,ny) && area(nx,ny)!=area.no_data){
      area(nx,ny)+=area(c.x,c.y);
      if((--dependency(nx,ny))==0)
        sources.push(grid_cell(nx,ny));
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
}
示例#8
0
int load_ascii_data(std::string filename, array2d<T> &elevations){
  std::ifstream fin;
  size_t file_size;
  int rows,columns;
  Timer load_time;
  ProgressBar progress;

  load_time.start();

  diagnostic_arg("Opening input ASCII-DEM file \"%s\"...",filename.c_str());
  fin.open(filename.c_str());
  if(!fin.good()){
    diagnostic("failed!\n");
    exit(-1);
  }
  diagnostic("succeeded.\n");

  diagnostic("Calculating file size...");
  fin.seekg(0, fin.end);
  file_size=fin.tellg();
  fin.seekg(0, fin.beg);
  diagnostic("succeeded.\n");

//  posix_fadvise(fileno(fin),0,0,POSIX_FADV_SEQUENTIAL);

  diagnostic("Reading DEM header...");
  fin>>must_be("ncols")         >>columns;
  fin>>must_be("nrows")         >>rows;
  fin>>must_be("xllcorner")     >>elevations.xllcorner;
  fin>>must_be("yllcorner")     >>elevations.yllcorner;
  fin>>must_be("cellsize")      >>elevations.cellsize;
  try {
    fin>>must_be("NODATA_value")  >>elevations.no_data;
  } catch (std::string e) {
    std::cerr<<e<<std::endl;
    std::cerr<<"Continuing without a NoData value!"<<std::endl;
  }
  diagnostic("succeeded.\n");

  diagnostic_arg("The loaded DEM will require approximately %ldMB of RAM.\n",columns*rows*((long)sizeof(float))/1024/1024);

  diagnostic("Resizing elevation matrix...");  //TODO: Consider abstracting this block
  elevations.resize(columns,rows);
  diagnostic("succeeded.\n");

  diagnostic("%%Reading elevation matrix...\n");
  progress.start(file_size);

  elevations.data_cells=0;
  for(int y=0;y<rows;y++){
    progress.update(fin.tellg()); //Todo: Check to see if ftell fails here?
    for(int x=0;x<columns;x++){
      fin>>elevations(x,y);
      if(elevations(x,y)!=elevations.no_data)
        elevations.data_cells++;
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  fin.close();

  diagnostic_arg(
    "Read %ld cells, of which %ld contained data (%ld%%).\n",
    elevations.width()*elevations.height(), elevations.data_cells,
    elevations.data_cells*100/elevations.width()/elevations.height()
  );

  load_time.stop();
  diagnostic_arg("Read time was: %lfs\n", load_time.accumulated());

  return 0;
}
示例#9
0
int read_floating_data(
  const std::string basename,
  array2d<T> &grid
){
  Timer io_time;
  ProgressBar progress;
  std::string fn_header(basename), fn_data(basename);

  //TODO: The section below should work, but is something of an abomination
  if(typeid(T)==typeid(float)){
    fn_header+=".hdr";
    fn_data+=".flt";
  } else if (typeid(T)==typeid(double)){
    fn_header+=".hdr";
    fn_data+=".dflt";
  } else {
    std::cerr<<"Cannot read floating type data into this format!"<<std::endl;
    exit(-1);
  }

  int columns, rows;
  std::string byteorder;

  io_time.start();


  {
    std::ifstream fin;
    diagnostic_arg("Opening floating-point header file \"%s\" for reading...",fn_header.c_str());
    fin.open(fn_header.c_str());
    if(fin==NULL){
      diagnostic("failed!\n");
      exit(-1);
    }
    diagnostic("succeeded.\n");


    diagnostic("Reading DEM header...");
    fin>>must_be("ncols")         >>columns;
    fin>>must_be("nrows")         >>rows;
    fin>>must_be("xllcorner")     >>grid.xllcorner;
    fin>>must_be("yllcorner")     >>grid.yllcorner;
    fin>>must_be("cellsize")      >>grid.cellsize;
    fin>>must_be("NODATA_value")  >>grid.no_data;
    fin>>must_be("BYTEORDER")     >>byteorder;
    diagnostic("succeeded.\n");
    fin.close();
  }

  diagnostic_arg("The loaded DEM will require approximately %ldMB of RAM.\n",columns*rows*((long)sizeof(float))/1024/1024);

  diagnostic("Resizing grid...");  //TODO: Consider abstracting this block
  grid.resize(columns,rows);
  diagnostic("succeeded.\n");



  diagnostic_arg("Opening floating-point data file \"%s\" for reading...",fn_data.c_str());

  {
    std::ifstream fin(fn_data.c_str(), std::ios::binary | std::ios::in);
    if(!fin.is_open()){
      diagnostic("failed!\n");
      exit(-1);  //TODO: Need to make this safer! Don't just close after all that work!
    }
    diagnostic("succeeded.\n");


    diagnostic("%%Reading data...\n");
    progress.start(columns*rows);
    grid.data_cells=0;
    for(int y=0;y<rows;++y){
      progress.update(y*columns); //Todo: Check to see if ftell fails here?
      for(int x=0;x<columns;++x){
        fin.read(reinterpret_cast<char*>(&grid(x,y)), std::streamsize(sizeof(T)));
        if(grid(x,y)!=grid.no_data)
          grid.data_cells++;
      }
    }
    io_time.stop();
    diagnostic_arg(SUCCEEDED_IN,progress.stop());

  }

  diagnostic_arg(
    "Read %ld cells, of which %ld contained data (%ld%%).\n",
    grid.width()*grid.height(), grid.data_cells,
    grid.data_cells*100/grid.width()/grid.height()
  );

  diagnostic_arg("Read time was: %lf\n", io_time.accumulated());

  return 0;
}
示例#10
0
int write_floating_data(
  const std::string basename,
  const array2d<T> &output_grid
){
  Timer write_time;
  ProgressBar progress;
  std::string fn_header(basename), fn_data(basename);

  //TODO: The section below should work, but is something of an abomination
  if(typeid(T)==typeid(float)){
    fn_header+=".hdr";
    fn_data+=".flt";
  } else if (typeid(T)==typeid(double)){
    fn_header+=".hdr";
    fn_data+=".dflt";
  } else {
    std::cerr<<"Cannot write floating type data into this format!"<<std::endl;
    exit(-1);
  }

  write_time.start();


  {
    diagnostic_arg("Opening floating-point header file \"%s\" for writing...",fn_header.c_str());
    std::ofstream fout;
    fout.open(fn_header.c_str());
    if(!fout.is_open()){
      diagnostic("failed!\n");
      exit(-1);  //TODO: Need to make this safer! Don't just close after all that work!
    }
    diagnostic("succeeded.\n");

    diagnostic("Writing floating-point header file...");
    fout<<"ncols\t\t"<<output_grid.width()<<std::endl;
    fout<<"nrows\t\t"<<output_grid.height()<<std::endl;
    fout<<"xllcorner\t"<<std::fixed<<std::setprecision(10)<<output_grid.xllcorner<<std::endl;
    fout<<"yllcorner\t"<<std::fixed<<std::setprecision(10)<<output_grid.yllcorner<<std::endl;
    fout<<"cellsize\t"<<std::fixed<<std::setprecision(10)<<output_grid.cellsize<<std::endl;
    fout<<"NODATA_value\t"<<std::fixed<<std::setprecision(10)<<output_grid.no_data<<std::endl;
    fout<<"BYTEORDER\tLSBFIRST"<<std::endl; //TODO
    fout.close();
    diagnostic("succeeded.\n");
  }


  diagnostic_arg("Opening floating-point data file \"%s\" for writing...",fn_data.c_str());

  {
    std::ofstream fout(fn_data.c_str(), std::ios::binary | std::ios::out);
    if(!fout.is_open()){
      diagnostic("failed!\n");
      exit(-1);  //TODO: Need to make this safer! Don't just close after all that work!
    }
    diagnostic("succeeded.\n");

    diagnostic("%%Writing floating-point data file...\n");
    progress.start( output_grid.width()*output_grid.height() );
    for(int y=0;y<output_grid.height();++y){
      progress.update( y*output_grid.width() );
      for(int x=0;x<output_grid.width();++x)
        fout.write(reinterpret_cast<const char*>(&output_grid(x,y)), std::streamsize(sizeof(T)));
    }
    fout.close();
    write_time.stop();
    diagnostic_arg(SUCCEEDED_IN,progress.stop());
  }

  diagnostic_arg("Write time was: %lf\n", write_time.accumulated());

  return 0;
}
示例#11
0
int output_ascii_data(
  const std::string filename,
  const array2d<T> &output_grid,
  int precision=8
){
  std::ofstream fout;
  std::string outputsep=" ";
  int output_type=OUTPUT_DEM;
  Timer write_time;
  ProgressBar progress;

  write_time.start();

  diagnostic_arg("Opening ASCII output file \"%s\"...",filename.c_str());
  fout.open(filename.c_str());
  if(!fout.is_open()){
    diagnostic("failed!\n");
    exit(-1);  //TODO: Need to make this safer! Don't just close after all that work!
  }
  diagnostic("succeeded.\n");

  //OmniGlyph output
  if(filename.substr(filename.length()-4)==".omg"){
    outputsep="|";
    output_type=OUTPUT_OMG;
    diagnostic("Writing OmniGlyph file header...");
    fout<<"Contents: Pixel array"<<std::endl;
    fout<<std::endl;
    fout<<"Width:    "<<output_grid.width()<<std::endl;
    fout<<"Height:   "<<output_grid.height()<<std::endl;
    fout<<std::endl;
    fout<<"Spectral bands:   1"<<std::endl;
    fout<<"Bits per band:   32"<<std::endl;
    fout<<"Range of values:   "<<output_grid.min()<<","<<output_grid.max()<<std::endl;
    fout<<"Actual range:   "<<output_grid.no_data<<","<<output_grid.max()<<std::endl;  //TODO: Assumes no_data is a small negative value
    fout<<"Gamma exponent:   0."<<std::endl;
    fout<<"Resolution:   100 pixels per inch"<<std::endl;
    fout<<std::endl;
    fout<<"|"<<std::endl;
  } else {
    diagnostic("Writing ArcGrid ASCII file header...");
    fout<<"ncols\t\t"<<output_grid.width()<<std::endl;
    fout<<"nrows\t\t"<<output_grid.height()<<std::endl;
    fout<<"xllcorner\t"<<std::fixed<<std::setprecision(precision)<<output_grid.xllcorner<<std::endl;
    fout<<"yllcorner\t"<<std::fixed<<std::setprecision(precision)<<output_grid.yllcorner<<std::endl;
    fout<<"cellsize\t"<<std::fixed<<std::setprecision(precision)<<output_grid.cellsize<<std::endl;
    fout<<"NODATA_value\t"<<std::fixed<<std::setprecision(precision);
    if(sizeof(T)==1)  //TODO: Crude way of detecting chars and bools
      fout<<(int)output_grid.no_data<<std::endl;
    else
      fout<<output_grid.no_data<<std::endl;
  }
  diagnostic("succeeded.\n");

  diagnostic("%%Writing ArcGrid ASCII file data...\n");
  progress.start( output_grid.width()*output_grid.height() );
  fout.precision(precision);
  fout.setf(std::ios::fixed);
  for(int y=0;y<output_grid.height();y++){
    progress.update( y*output_grid.width() );
    if(output_type==OUTPUT_OMG)
      fout<<"|";
    for(int x=0;x<output_grid.width();x++)
      if(sizeof(T)==1)  //TODO: Crude way of detecting chars and bools
        fout<<(int)output_grid(x,y)<<outputsep;
      else
        fout<<output_grid(x,y)<<outputsep;
    fout<<std::endl;
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  fout.close();

  write_time.stop();
  diagnostic_arg("Write time was: %lf\n", write_time.accumulated());

  return 0;
}
示例#12
0
void dinf_upslope_area_interval(const float_2d &flowdirs, grid_engine< boost::numeric::interval<T> > &area){
  char_2d dependency;
  std::queue<grid_cell> sources;
  ProgressBar progress;

  diagnostic_arg("The sources queue will require at most approximately %ldMB of RAM.\n",flowdirs.width()*flowdirs.height()*((long)sizeof(grid_cell))/1024/1024);

  diagnostic("Setting up the dependency matrix...");
  dependency.copyprops(flowdirs);
  dependency.init(0);
  diagnostic("succeeded.\n");

  diagnostic("Setting up the area matrix...");
  area.copyprops(flowdirs);
  area.init((float)0);
  area.no_data=dinf_NO_DATA;
  diagnostic("succeeded.\n");

  bool has_cells_without_flow_directions=false;
  diagnostic("%%Calculating dependency matrix & setting no_data cells...\n");
  progress.start( flowdirs.width()*flowdirs.height() );
  #pragma omp parallel for reduction(|:has_cells_without_flow_directions)
  for(int x=0;x<flowdirs.width();x++){
    progress.update( x*flowdirs.height() );
    for(int y=0;y<flowdirs.height();y++){
      if(flowdirs(x,y)==flowdirs.no_data){
        area(x,y)=area.no_data;
        dependency(x,y)=9;  //Note: This is an unnecessary safety precaution
        continue;
      }
      if(flowdirs(x,y)==NO_FLOW){
        has_cells_without_flow_directions=true;
        continue;
      }
      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.in_grid(nlx,nly) && flowdirs(nlx,nly)!=flowdirs.no_data )
        dependency(nlx,nly)++;
      if( flowdirs.in_grid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.no_data )
        dependency(nhx,nhy)++;
    }
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
  if(has_cells_without_flow_directions)
    diagnostic("\033[91mNot all cells had defined flow directions! This implies that there will be digital dams!\033[39m\n");

  diagnostic("%%Locating source cells...\n");
  progress.start( flowdirs.width()*flowdirs.height() );
  for(int x=0;x<flowdirs.width();x++){
    progress.update( x*flowdirs.height() );
    for(int y=0;y<flowdirs.height();y++)
      if(flowdirs(x,y)==flowdirs.no_data)
        continue;
      else if(flowdirs(x,y)==NO_FLOW)
        continue;
      else if(dependency(x,y)==0)
        sources.push(grid_cell(x,y));
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());

  diagnostic("%%Calculating up-slope areas...\n");
  progress.start( flowdirs.data_cells );
  long int ccount=0;
  while(sources.size()>0){
    grid_cell c=sources.front();
    sources.pop();

    ccount++;
    progress.update(ccount);

    if(flowdirs(c.x,c.y)==flowdirs.no_data)  //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.in_grid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.no_data)
      area(nhx,nhy)+=area(c.x,c.y)*(T)phigh;

    if(n_low!=-1){
      nlx=c.x+dinf_dx[n_low];
      nly=c.y+dinf_dy[n_low];
      if(flowdirs.in_grid(nlx,nly) && flowdirs(nlx,nly)!=flowdirs.no_data){
        area(nlx,nly)+=area(c.x,c.y)*(T)plow;
        if((--dependency(nlx,nly))==0)
          sources.push(grid_cell(nlx,nly));
      }
    }

    if( flowdirs.in_grid(nhx,nhy) && flowdirs(nhx,nhy)!=flowdirs.no_data && (--dependency(nhx,nhy))==0)
      sources.push(grid_cell(nhx,nhy));
  }
  diagnostic_arg(SUCCEEDED_IN,progress.stop());
}