/* 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; }
/* 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; }
/* ---------------------------------------------------------------------- */ 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; }