Esempio n. 1
0
/* open fill's output stream and get all info from there; delete
   fillStream */
AMI_STREAM<sweepItem>*
fillstr2sweepstr(AMI_STREAM<waterWindowBaseType>* fillStream) {

  Rtimer rt;
  AMI_STREAM<sweepItem> *sweepstr;  

  rt_start(rt);
  
  if (stats)
    stats->comment("creating sweep stream from fill output stream");
  
  assert(fillStream->stream_len() == nrows * ncols);
  
  /* create the sweep stream */
  sweepstr = new AMI_STREAM<sweepItem>();
  waterWindowBaseType2sweepItem(fillStream, nrows, ncols,
				nodataType::ELEVATION_NODATA, sweepstr);
  delete fillStream;

  if (opt->verbose) {
    fprintf(stderr,  "sweep stream size: %.2fMB",
			(double)sweepstr->stream_len()*sizeof(sweepItem)/(1<<20));
    fprintf(stderr,  " (%d items, item size=%d B\n ", 
			(int)sweepstr->stream_len(), sizeof(sweepItem));;
  }
  if (stats)
    stats->recordLength("sweep stream", sweepstr);
  
  /* sort sweep stream by (increasing) priority */
  if (opt->verbose) {
    fprintf(stderr, "sorting sweep stream (%.2fMB) in priority order\n", 
	    (double)sweepstr->stream_len()*sizeof(sweepItem)/(1<<20));
  }
  if (stats)
    stats->comment("sorting sweep stream");
  sort(&sweepstr, PrioCmpSweepItem());

  rt_stop(rt);
  
  if (stats) {
      stats->recordTime("create sweep stream", rt);
      stats->recordLength("(sorted) sweep stream", sweepstr);
  }

  return sweepstr;
}
Esempio n. 2
0
AMI_STREAM<elevation_type> *
classifyNodata(AMI_STREAM<elevation_type> *elstr) {
  Rtimer rt;

  rt_start(rt);
  if (stats)
    stats->comment("finding nodata", opt->verbose);
  detectEdgeNodata md(nrows, ncols, nodataType::ELEVATION_NODATA);
  md.generateNodata(*elstr);
  if (stats)
    *stats << "nodata stream length = " << md.getNodata()->stream_len() << endl;
  {
    char * foo;
    md.getNodata()->name(&foo); 
    if (stats)
      *stats << "nodata stream name: " << foo << endl;
  }
  rt_stop(rt);
  if (stats)
    stats->recordTime("classifyNodata::generate nodata", rt);

  rt_start(rt);
  if (stats)
    stats->comment("relabeling nodata",  opt->verbose);
  md.relabelNodata();  /* re-assign labels (combine connected plateaus) */
  rt_stop(rt);
  if (stats)
    stats->recordTime("classifyNodata::relabeling",  rt);
  
  rt_start(rt);
  if (stats)
    stats->comment("merging relabeled grid",  opt->verbose);
  AMI_STREAM<elevation_type> *mergeStr;
  mergeStr = md.merge();
  rt_stop(rt);
  if (stats)
    stats->recordTime("classifyNodata::merge",  rt);

  mergeStr->seek(0);
  return mergeStr;
}
Esempio n. 3
0
/* collapse labels; remove nodata regions */
void
detectEdgeNodata::relabelNodata() {
  AMI_err ae;
  nodataType *pt;

  /* sort by label */
  if (stats)
    NODATA_DEBUG *stats << "sort nodataStream (by nodata label): ";
  AMI_STREAM<nodataType> *sortedInStream;
  sortedInStream = sort(nodataStream, labelCmpNodataType());
  delete nodataStream;

  nodataStream = new AMI_STREAM<nodataType>();

  while((ae = sortedInStream->read_item(&pt)) == AMI_ERROR_NO_ERROR) {
	cclabel_type root = colTree.findNextRoot(pt->label);
	assert(root <= pt->label);
	pt->label = root;
	ae = nodataStream->write_item(*pt);
	assert(ae == AMI_ERROR_NO_ERROR);
  }

  delete sortedInStream;
}
Esempio n. 4
0
void
flow_waterWindower::processWindow(dimension_type i, dimension_type j, 
				  waterWindowBaseType *a,
				  waterWindowBaseType *b,
				  waterWindowBaseType *c) {
  
  elevation_type el1[3], el2[3], el3[3];
  toporank_type ac1[3], ac2[3], ac3[3];
  
  if (is_nodata(b[1].el)) {
    /*sweep_str does not include nodata */
    return;
  }
  /*#ifdef  COMPRESSED_WINDOWS
	sweepItem win = sweepItem(i, j, a, b, c);
	#else
  */
  for (int k=0; k<3; k++) {
    el1[k] = a[k].el;
    ac1[k] = -a[k].depth; /*WEIRD */
    el2[k] = b[k].el;
    ac2[k] = -b[k].depth; /*WEIRD*/
    el3[k] = c[k].el;
    ac3[k] = -c[k].depth; /*WEIRD*/
  }
  /*
	genericWindow<elevation_type> e_win(el);
	genericWindow<toporank_type> a_win(ac);
	sweepItem win = sweepItem(i, j, b[1].dir, e_win, a_win);
  */
  sweepItem win = sweepItem(i, j, b[1].dir, el1, el2, el3, ac1, ac2, ac3);
  /* #endif */
 
  AMI_err ae = sweep_str->write_item(win);
  assert(ae == AMI_ERROR_NO_ERROR);
}
Esempio n. 5
0
void ccforest<T>::findAllRoots(int depth) {
  if(foundAllRoots) return;
  foundAllRoots = 1;
  Rtimer rt;
  rt_start(rt);

  if(depth > 5) {
	cerr << "WARNING: excessive recursion in ccforest (ignored)" << endl;
  }

  int explicitRootCount = 0;
  assert(!superTree);
  superTree = new ccforest<T>();

  if (stats)
    DEBUG_CCFOREST *stats << "sort edgeStream (by cclabel)): ";
  keyCmpKeyvalueType<T> fo;
  sort(&edgeStream, fo); /* XXX -changed this to use a cmp obj  */

  /* time forward processing */
  EMPQueueAdaptive<cckeyvalue,T> *pq =
	new EMPQueueAdaptive<cckeyvalue,T>();	/* parent queue */

  size_t streamLength = edgeStream->stream_len();
  T prevSrc = T(-1);
  T parent = T(-1);
  ccedge prevEdge;
  for(unsigned int i=0; i<streamLength; i++) {
	ccedge *e;
	AMI_err ae = edgeStream->read_item(&e);
	assert(ae == AMI_ERROR_NO_ERROR);

#if(0)
	if (stats) {
	    DEBUG_CCFOREST *stats << "------------------------------" << endl;
	    DEBUG_CCFOREST *stats << "processing edge " << *e << endl;
	}
	DEBUG_CCFOREST pq->print();
#endif

	if(*e == prevEdge) {
	  if (stats)
	    DEBUG_CCFOREST *stats << "\tduplicate " << *e << " removed\n";
	  continue; /* already have this done */
	}
	prevEdge = *e;

	if (stats)
	  DEBUG_CCFOREST *stats << "processing edge " << *e << endl;

	/* find root (assign parent) */
	if(e->src() != prevSrc) {
	  prevSrc = e->src();
	  cckeyvalue kv;
	  /* check if we have a key we don't use. */
	  while(pq->min(kv) && (kv.getPriority() < e->src())) {
		pq->extract_min(kv);
		assert(kv.src() >= kv.dst());
		removeDuplicates(kv.src(), kv.dst(), *pq);
		ae = rootStream->write_item(kv); /* save root */
		assert(ae == AMI_ERROR_NO_ERROR);	
	  }
	  /* try to find our root */
	  if(pq->min(kv) && ((e->src() == kv.getPriority()))) {
		pq->extract_min(kv);
		parent = kv.getValue();
		removeDuplicates(e->src(), parent, *pq);
	  } else {
		parent = e->src();		/* we are root */
		explicitRootCount++;
		/* technically, we could skip this part. the lookup function
           automatically assumes that values without parents are roots */
	  }

	  /* save result */
	  cckeyvalue kroot(e->src(), parent);
	  assert(kroot.src() >= kroot.dst());
	  ae = rootStream->write_item(kroot);
	  assert(ae == AMI_ERROR_NO_ERROR);
	}
#ifndef NDEBUG
	cckeyvalue kv2;
	assert(pq->is_empty() || (pq->min(kv2) && kv2.getPriority() > e->src()));
#endif

	/* insert */
	cckeyvalue kv(e->dst(), parent);
	assert(kv.src() >= kv.dst());
	pq->insert(kv);

	/* cout << "identified: " << kroot << endl; */
  }

  /* drain the priority queue */
  if (stats)
    DEBUG_CCFOREST *stats << "draining priority queue" << endl;
  while (!pq->is_empty()) {
	cckeyvalue kv;
	pq->extract_min(kv);
	assert(kv.src() >= kv.dst());
	if (stats)
	  DEBUG_CCFOREST *stats << "processing edge " << kv << endl;

	removeDuplicates(kv.src(), kv.dst(), *pq);
	AMI_err ae = rootStream->write_item(kv);
	assert(ae == AMI_ERROR_NO_ERROR);
  }
  delete pq;

  /* note that rootStream is naturally ordered by src */

  if(superTree->size()) {
        if (stats) {
	    DEBUG_CCFOREST *stats << "resolving cycles..." << endl;
	    /* printStream(rootStream); */
	    DEBUG_CCFOREST *stats << "sort rootStream: ";
        }

	AMI_STREAM<cckeyvalue> *sortedRootStream; 
	dstCmpKeyvalueType<T> dstfo;
	sortedRootStream = sort(rootStream, dstfo); 
	/* XXX replaced this to use a cmp object -- laura
	   AMI_STREAM<cckeyvalue>*sortedRootStream=new AMI_STREAM<cckeyvalue>();
	   AMI_err ae = AMI_sort(rootStream, sortedRootStream, valueCmp); 
	   assert(ae == AMI_ERROR_NO_ERROR);
	*/
	delete rootStream;

	cckeyvalue *kv;
	T parent;
	AMI_err ae;
	
	AMI_STREAM<cckeyvalue>* relabeledRootStream
	  = new AMI_STREAM<cckeyvalue>();
	ae = sortedRootStream->seek(0);
	superTree->findAllRoots(depth+1);
	while((ae = sortedRootStream->read_item(&kv)) == AMI_ERROR_NO_ERROR) {
	  parent = superTree->findNextRoot(kv->dst());
	  ae = relabeledRootStream->write_item(cckeyvalue(kv->src(), parent));
	  assert(ae == AMI_ERROR_NO_ERROR);
	}
	delete sortedRootStream;

        if (stats)
	    DEBUG_CCFOREST *stats << "sort relabeledRootStream: ";
	rootStream = sort(relabeledRootStream, fo);
	/* laura: changed  this
	   rootStream = new AMI_STREAM<cckeyvalue>();
	   ae = AMI_sort(relabeledRootStream, rootStream);
	   assert(ae == AMI_ERROR_NO_ERROR);
	*/
	delete relabeledRootStream;

        if (stats)
	    DEBUG_CCFOREST *stats << "resolving cycles... done." << endl;
  }
  rootStream->seek(0);

  if (stats){
    DEBUG_CCFOREST *stats << "Rootstream length="
					  << rootStream->stream_len() << endl;
    DEBUG_CCFOREST printStream(*stats, rootStream);
    DEBUG_CCFOREST *stats << "Explicit root count=" << explicitRootCount << endl;
  }

  rt_stop(rt);
  if (stats)
    stats->recordTime("ccforest::findAllRoots",  (long int)rt_seconds(rt));
}
Esempio n. 6
0
/* deletes fillStream */
void
computeFlowAccumulation(AMI_STREAM<waterWindowBaseType>* fillStream,
			AMI_STREAM<sweepOutput> *& outstr) {
  Rtimer rt, rtTotal;
  AMI_STREAM<sweepItem> *sweepstr;

  rt_start(rtTotal);
  assert(fillStream && outstr == NULL);
  if (stats) {
      stats->comment("------------------------------");
      stats->comment("COMPUTING FLOW ACCUMULATION");
  }
  
  { /* timestamp stats file and print memory */
    time_t t = time(NULL);
    char buf[BUFSIZ];
    if(t == (time_t)-1) {
      perror("time");
      exit(1);
    }
#ifdef __MINGW32__
    strcpy(buf, ctime(&t));
#else
    ctime_r(&t, buf);
    buf[24] = '\0';
#endif
    if (stats) {
	stats->timestamp(buf);
	*stats << endl;  
    }
    
    size_t mm_size = (opt->mem  << 20); /* (in bytes) */
    formatNumber(buf, mm_size);
    if (stats)
	*stats << "memory size: " << buf << " bytes\n";
  }

  /* create sweepstream using info from  fillStream  */
  sweepstr = fillstr2sweepstr(fillStream); 
  /* fillStream is deleted inside fillstr2sweepstr */

  /* sweep and dump outputs into outStream; trustdir=1 */
  outstr = sweep(sweepstr, opt->d8cut, 1);
  assert(outstr->stream_len() == sweepstr->stream_len());
  delete sweepstr;

  /* sort output stream into a grid */
  rt_start(rt);
  if (stats) {
      stats->comment( "sorting sweep output stream");
      stats->recordLength("output stream", outstr);
  }
  sort(&outstr, ijCmpSweepOutput());
  rt_stop(rt);
  if (stats) {
      stats->recordLength("output stream", outstr);
      stats->recordTime("sorting output stream", rt);
  }

  rt_stop(rtTotal);
  if (stats)
    stats->recordTime("compute flow accumulation", rtTotal);

#ifdef SAVE_ASCII
  printStream2Grid(outstr, nrows, ncols, "flowaccumulation.asc", 
		   printAccumulationAscii());
  printStream2Grid(outstr, nrows, ncols, "tci.asc", 
		   printTciAscii());
#endif
  return;
}
Esempio n. 7
0
/* ---------------------------------------------------------------------- */
int
main(int argc, char *argv[]) {
  struct GModule *module;
  Rtimer rtTotal;    
  char buf[BUFSIZ];

  /* initialize GIS library */
  G_gisinit(argv[0]);

 
  module = G_define_module();
#ifdef ELEV_SHORT
  module->description = _("Flow computation for massive grids (integer version).");
#endif
#ifdef ELEV_FLOAT
  module->description = _("Flow computation for massive grids (float version).");
#endif
  G_add_keyword(_("raster"));
  G_add_keyword(_("hydrology"));

  /* read user options; fill in global <opt> */  
  opt = (userOptions*)malloc(sizeof(userOptions));
  assert(opt);
  
  region = (struct Cell_head*)malloc(sizeof(struct Cell_head));
  assert(region);

  parse_args(argc, argv);

  /* get the current region and dimensions */  
  G_get_set_window(region);

  check_args();

  int nr = Rast_window_rows();
  int nc = Rast_window_cols();
  if ((nr > dimension_type_max) || (nc > dimension_type_max)) {
    G_fatal_error(_("[nrows=%d, ncols=%d] dimension_type overflow -- "
	"change dimension_type and recompile"), nr, nc);
  } else {
    nrows = (dimension_type)nr;
    ncols = (dimension_type)nc;
  }

  G_verbose_message( _("Region size is %d x %d"), nrows, ncols);
 
  /* check STREAM path (the place where intermediate STREAMs are placed) */
  sprintf(buf, "%s=%s",STREAM_TMPDIR, opt->streamdir);
  /* don't pass an automatic variable; putenv() isn't guaranteed to make a copy */
  putenv(G_store(buf));
  if (getenv(STREAM_TMPDIR) == NULL) {
    fprintf(stderr, "%s:", STREAM_TMPDIR);
    G_fatal_error("not set");
  } else {
    fprintf(stderr, "STREAM temporary files in %s  ",
	    getenv(STREAM_TMPDIR)); 
	fprintf(stderr, "(THESE INTERMEDIATE STREAMS WILL NOT BE DELETED IN CASE OF ABNORMAL TERMINATION OF THE PROGRAM. TO SAVE SPACE PLEASE DELETE THESE FILES MANUALLY!)\n");
  }
  
  /* open the stats file */
  stats = new statsRecorder(opt->stats);
  record_args(argc, argv);
  {
    char buf[BUFSIZ];
    long grid_size = nrows * ncols;
    *stats << "region size = " <<  formatNumber(buf, grid_size) << " elts "
	   << "(" << nrows << " rows x " << ncols << " cols)\n";

    stats->flush();
  }

  /* set up STREAM memory manager */
  size_t mm_size = (size_t) opt->mem << 20; /* opt->mem is in MB */
  MM_manager.set_memory_limit(mm_size);
  if (opt->verbose) {
	MM_manager.warn_memory_limit();
  } else {
	MM_manager.ignore_memory_limit();
  }
  MM_manager.print_limit_mode();


  /* initialize nodata */
  nodataType::init();
  *stats << "internal nodata value: " << nodataType::ELEVATION_NODATA << endl;
   
  /* start timing -- after parse_args, which are interactive */
  rt_start(rtTotal);

#ifndef JUMP2FLOW 
  /* read elevation into a stream */
  AMI_STREAM<elevation_type> *elstr=NULL;
  long nodata_count;
  elstr = cell2stream<elevation_type>(opt->elev_grid, elevation_type_max,
									  &nodata_count);
  /* print the largest interm file that will be generated */
  printMaxSortSize(nodata_count);
  

  /* -------------------------------------------------- */
  /* compute flow direction and filled elevation (and watersheds) */
  AMI_STREAM<direction_type> *dirstr=NULL;
  AMI_STREAM<elevation_type> *filledstr=NULL;
  AMI_STREAM<waterWindowBaseType> *flowStream=NULL;
  AMI_STREAM<labelElevType> *labeledWater = NULL;

  flowStream=computeFlowDirections(elstr, filledstr, dirstr, labeledWater);

  delete elstr;

  /* write streams to GRASS raster maps */
  stream2_CELL(dirstr, nrows, ncols, opt->dir_grid);
  delete dirstr;
#ifdef ELEV_SHORT
  stream2_CELL(filledstr, nrows, ncols, opt->filled_grid);
#else
  stream2_CELL(filledstr, nrows, ncols, opt->filled_grid,true);
#endif
  delete filledstr; 

  stream2_CELL(labeledWater, nrows, ncols, labelElevTypePrintLabel(), 
			   opt->watershed_grid);
  setSinkWatershedColorTable(opt->watershed_grid);
  delete labeledWater;
  
#else 
  AMI_STREAM<waterWindowBaseType> *flowStream;
  char path[GPATH_MAX];

  sprintf(path, "%s/flowStream", streamdir->answer);
  flowStream = new AMI_STREAM<waterWindowBaseType>(path);
  fprintf(stderr, "flowStream opened: len=%d\n", flowStream->stream_len());
  fprintf(stderr, "jumping to flow accumulation computation\n");
#endif
  
  /* -------------------------------------------------- */
  /* compute flow accumulation (and tci) */
  AMI_STREAM<sweepOutput> *outstr=NULL;
  
  computeFlowAccumulation(flowStream, outstr);
  /* delete flowStream -- deleted inside */

  /* write output stream to GRASS raster maps */
#ifdef OUTPUT_TCI
  stream2_FCELL(outstr, nrows, ncols, printAccumulation(), printTci(),
		opt->flowaccu_grid, opt->tci_grid);
#else 
  stream2_FCELL(outstr, nrows, ncols, printAccumulation(), opt->flowaccu_grid);
#endif

  setFlowAccuColorTable(opt->flowaccu_grid);

  delete outstr;
  
  rt_stop(rtTotal);
  stats->recordTime("Total running time: ", rtTotal);
  stats->timestamp("end");

  G_done_msg(" ");
  
  /* free the globals */
  free(region);
  free(opt);
  delete stats;

  return 0;
}
Esempio n. 8
0
void
detectEdgeNodata::processWindow(dimension_type row, dimension_type col,
				elevation_type &point,
				elevation_type *a,
				elevation_type *b,
				elevation_type *c) {
  AMI_err ae;
  static nodataType prevCell;	/* cell on left (gets initialized) */

  assert(row>=0);
  assert(col>=0);

  /* create window and write out */
  ElevationWindow win(a, b, c);
  fillPit(win);          /* fill pit in window */
  ae = elevStream->write_item(win.get());
  assert(ae == AMI_ERROR_NO_ERROR);


  /* only interested in nodata in this pass */
  if(win.get() !=  nodata) {
	prevCell.label = LABEL_UNDEF;
	return;
  }

  if(col == 0) prevCell.label = LABEL_UNDEF; /* no left cell */

  /* now check for continuing plateaus */
  nodataType *ptarr = 
	getNodataForward(row-1, col-1, nr, nc);

  /* make sure we use boundary label if appropriate */
  cclabel_type crtlabel;
  crtlabel = (IS_BOUNDARY(row,col,nr, nc) ? LABEL_BOUNDARY : LABEL_UNDEF);

  for(int i=0; i<4; i++) {
	if(win.get(i) != win.get()) continue; /* only interesting if same elev */

	/* determine label for cell */
	cclabel_type label = LABEL_UNDEF;
	if(i<3) {
	  if(ptarr[i].valid) label = ptarr[i].label;
	} else {
	  if(prevCell.valid) label = prevCell.label;
	}

	/* check for collisions */
	if(label != LABEL_UNDEF) {
	  if (crtlabel == LABEL_UNDEF) {
		crtlabel = label;
	  } else if(crtlabel != label) {  		  /* collision!! */
		/* pick smaller label, but prefer nodata */
		if(crtlabel==LABEL_BOUNDARY || crtlabel<label) { 
		  colTree.insert(crtlabel, label);
		} else {
		  colTree.insert(label, crtlabel);
		  crtlabel = label;
		}
	  }
	}
  }
  
  /* assign label if required */
  if(crtlabel == LABEL_UNDEF) {
	crtlabel = labelFactory::getNewLabel();
  }

  /* write this plateau point to the plateau stream */
  nodataType pt;
  prevCell = pt = nodataType(row, col, crtlabel);
  nodataQueue->enqueue(pt);

  /* NODATA_DEBUG *stats << "inserting " << pt << endl; */
  
  nodataStream->write_item(pt);	/*  save to file for later use */
}