int esys_release(struct esys* esys, ocn_entity_token_t token) { if(token >= OCN_MAX_ENTITIES) return OCN_ENTITY_ERR_RANGE; pthread_spin_lock(&esys->lock); struct entityslot* slot = &esys->slots[token]; if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED)) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_NONEXIST; } if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_ISOLATED)) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_ISOLATED; } /* --- */ FLAG_UNSET(slot->flags, ENTITYSLOT_FLAG_ISOLATED); /* --- */ pthread_spin_unlock(&esys->lock); return OCN_OK; }
int esys_del(struct esys* esys, ocn_entity_token_t token) { if(token >= OCN_MAX_ENTITIES) return OCN_ENTITY_ERR_RANGE; pthread_spin_lock(&esys->lock); struct entityslot* slot = &esys->slots[token]; if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED)) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_NONEXIST; } if(FLAG_GET(slot->flags, ENTITYSLOT_FLAG_ISOLATED)) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_ISOLATED; } /* --- */ entity_t* entity = &slot->entity; slot->flags = 0lu; esys->count--; /* --- */ pthread_spin_unlock(&esys->lock); entity_destroy(entity); return OCN_OK; }
int esys_unlink(struct esys* esys, ocn_entity_token_t token, ocn_entity_offset_t offset) { if(token >= OCN_MAX_ENTITIES) return OCN_ENTITY_ERR_RANGE; pthread_spin_lock(&esys->lock); struct entityslot* slot = &esys->slots[token]; if(!FLAG_GET(slot->flags, ENTITYSLOT_FLAG_USED)) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_NONEXIST; } if(offset >= OCN_ENTITY_MAX_REFS) { pthread_spin_unlock(&esys->lock); return OCN_ENTITY_ERR_OFFSET; } /* --- */ slot->entity.refs[offset] = 0lu; /* --- */ pthread_spin_unlock(&esys->lock); return OCN_OK; }
int find_pourpts(void) { int row, col; double easting, northing, stream_length; CELL old_elev, basin_num, no_basin, curr_basin; WAT_ALT wa; ASP_FLAG af; char is_swale; ocs_alloced = 2 * bas_thres; ocs = (OC_STACK *)G_malloc(ocs_alloced * sizeof(OC_STACK)); basin_num = 0; Rast_set_c_null_value(&no_basin, 1); stream_length = old_elev = 0; for (row = 0; row < nrows; row++) { G_percent(row, nrows, 1); northing = window.north - (row + .5) * window.ns_res; for (col = 0; col < ncols; col++) { seg_get(&aspflag, (char *)&af, row, col); cseg_get(&bas, &curr_basin, row, col); if (curr_basin == 0) cseg_put(&bas, &no_basin, row, col); cseg_get(&haf, &curr_basin, row, col); if (curr_basin == 0) cseg_put(&haf, &no_basin, row, col); is_swale = FLAG_GET(af.flag, SWALEFLAG); if (af.asp <= 0 && is_swale > 0) { basin_num += 2; if (arm_flag) { easting = window.west + (col + .5) * window.ew_res; fprintf(fp, "%5d drains into %5d at %3d %3d %.3f %.3f", (int)basin_num, 0, row, col, easting, northing); if (col == 0 || col == ncols - 1) { stream_length = .5 * window.ew_res; } else if (row == 0 || row == nrows - 1) { stream_length = .5 * window.ns_res; } else { stream_length = 0.0; } seg_get(&watalt, (char *) &wa, row, col); old_elev = wa.ele; } basin_num = def_basin(row, col, basin_num, stream_length, old_elev); } } } G_percent(nrows, nrows, 1); /* finish it */ n_basins = basin_num; G_free(ocs); return 0; }
int loop_hook(t_env *e) { if (FLAG_GET(e->flag, MASK_RECALC)) { recalc_scene(e); ft_post_processing(e); ft_printelapsed(e); FLAG_UNSET(e->flag, MASK_RECALC); } mlx_put_image_to_window(e->mlx, e->win, e->screen->img, 0, 0); return (0); }
void lsys_log(lsys_t* lsys, int type, const char* format, ...) { ocn_spin_lock(&lsys->lock); if(!FLAG_GET(lsys->flags, OCN_LOGGING)) { ocn_spin_unlock(&lsys->lock); return; } //ocn_time_current(&lsys->time); uint32_t timestamp = ocn_get_ticks(); snprintf(&lsys->data[lsys->head][0], LOGGER_HEADER_SIZE + 1, "(%08x)(%04u)[%s]: ", timestamp, lsys->head + 1, lsys_type_string(type)); va_list args; va_start(args, format); vsnprintf(&lsys->data[lsys->head][LOGGER_HEADER_SIZE], (OCN_LOGGER_MSG_SIZE + 1), format, args); va_end(args); // for now we also write the entry to stdout (this is bad, because I/O is slow) if(FLAG_GET(lsys->flags, OCN_LOGGING_STDOUT)) { fprintf(stdout, lsys->data[lsys->head]); fprintf(stdout, "\n"); //fflush(stdout); } // set head to next entry or rotate around if(lsys->head == (OCN_LOGGER_MAX - 1)) lsys->head = 0; else lsys->head++; ocn_spin_unlock(&lsys->lock); }
static int update_rid(struct globals *globals, int row, int col, int new_id) { int rown, coln, n; int neighbors[8][2]; int this_id; int ngbr_id; struct rc next; struct rclist rilist; int no_check; /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); Segment_put(&globals->rid_seg, (void *) &new_id, row, col); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); do { globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; if (!no_check) { /* get neighbour ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { rclist_add(&rilist, rown, coln); Segment_put(&globals->rid_seg, (void *) &new_id, rown, coln); } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); return 1; }
int sg_factor(void) { int r, c; CELL low_elev, hih_elev; double height, length, S, sin_theta; WAT_ALT wa; ASP_FLAG af; G_message(_("SECTION 5: RUSLE LS and/or S factor determination.")); for (r = nrows - 1; r >= 0; r--) { G_percent(nrows - r, nrows, 3); for (c = ncols - 1; c >= 0; c--) { seg_get(&aspflag, (char *)&af, r, c); if (FLAG_GET(af.flag, NULLFLAG)) continue; seg_get(&watalt, (char *) &wa, r, c); low_elev = wa.ele; cseg_get(&r_h, &hih_elev, r, c); dseg_get(&s_l, &length, r, c); height = 1.0 * (hih_elev - low_elev) / ele_scale; if (length > max_length) { height *= max_length / length; length = max_length; } sin_theta = height / sqrt(height * height + length * length); if (height / length < .09) S = 10.8 * sin_theta + .03; else S = 16.8 * sin_theta - .50; if (ls_flag) { length *= METER_TO_FOOT; len_slp_equ(length, sin_theta, S, r, c); } if (sg_flag) { dseg_put(&s_g, &S, r, c); } } } G_percent(nrows, nrows, 1); /* finish it */ return 0; }
static int find_best_neighbour(struct globals *globals, int row, int col, int this_id, struct NB_TREE *nbtree, int *reg_size, struct ngbr_stats **Rbest, int *best_n_row, int *best_n_col) { int rown, coln, n, count; int neighbors[8][2]; struct rc next, ngbr_rc; struct rclist rilist; int no_check; int ngbr_id; struct RB_TREE *visited; struct ngbr_stats Ri, Rk, *Rfound; double sim, best_sim; int best_n_id; int have_Ri; Ri.mean = G_malloc(globals->datasize); Rk.mean = G_malloc(globals->datasize); nbtree_clear(nbtree); FLAG_UNSET(globals->candidate_flag, row, col); visited = rbtree_create(cmp_rc, sizeof(struct rc)); ngbr_rc.row = row; ngbr_rc.col = col; rbtree_insert(visited, &ngbr_rc); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); count = 1; best_n_id = -1; best_sim = 2; do { have_Ri = 0; globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; ngbr_rc.row = rown; ngbr_rc.col = coln; if (!no_check && !rbtree_find(visited, &ngbr_rc)) { rbtree_insert(visited, &ngbr_rc); /* get neighbor ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { count++; rclist_add(&rilist, rown, coln); FLAG_UNSET(globals->candidate_flag, rown, coln); } else { /* different neighbour */ /* compare to this cell next.row, next.col */ if (!have_Ri) { Segment_get(globals->bands_out, (void *) Ri.mean, next.row, next.col); have_Ri = 1; } Segment_get(globals->bands_out, (void *) Rk.mean, rown, coln); sim = globals->calculate_similarity(&Ri, &Rk, globals); if (best_sim > sim) { best_sim = sim; best_n_id = ngbr_id; *best_n_row = rown; *best_n_col = coln; } /* find in neighbor tree */ Rk.id = ngbr_id; if ((Rfound = nbtree_find(nbtree, &Rk))) { Rfound->count++; if (*Rbest && (*Rbest)->count < Rfound->count) *Rbest = Rfound; } else { Rk.count = 1; Rk.row = rown; Rk.col = coln; nbtree_insert(nbtree, &Rk); if (!(*Rbest)) *Rbest = nbtree_find(nbtree, &Rk); } } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); rbtree_destroy(visited); G_free(Ri.mean); G_free(Rk.mean); *reg_size = count; return best_n_id; }
int mean_shift(struct globals *globals) { int row, col, t, n; int mwrow, mwrow1, mwrow2, mwnrows, mwcol, mwcol1, mwcol2, mwncols, radiusc; double hspat, hspec, hspat2, hspec2, sigmaspat2, sigmaspec2; double hspecad, hspecad2; double ka2; double w, wsum; LARGEINT n_changes; double alpha2, maxdiff2; struct ngbr_stats Rin, Rout, Rn; double diff, diff2; SEGMENT *seg_tmp; double mindiff, mindiffzero, mindiffavg, mindiffzeroavg; double avgdiff, avgdiffavg; LARGEINT nvalid, count; int do_gauss = 0, do_adaptive, do_progressive; Rin.mean = G_malloc(globals->datasize); Rout.mean = G_malloc(globals->datasize); Rn.mean = G_malloc(globals->datasize); alpha2 = globals->alpha * globals->alpha; do_adaptive = globals->ms_adaptive; do_progressive = globals->ms_progressive; globals->candidate_count = 0; flag_clear_all(globals->candidate_flag); /* Set candidate flag to true/1 for all non-NULL cells */ for (row = globals->row_min; row < globals->row_max; row++) { for (col = globals->col_min; col < globals->col_max; col++) { if (!(FLAG_GET(globals->null_flag, row, col))) { FLAG_SET(globals->candidate_flag, row, col); globals->candidate_count++; } } } /* spatial bandwidth */ hspat = globals->hs; if (hspat < 1) { hspat = 1.5; globals->hs = hspat; } hspat2 = hspat * hspat; sigmaspat2 = hspat2 / 9.; radiusc = hspat; /* radius in cells truncated to integer */ mwnrows = mwncols = radiusc * 2 + 1; /* estimate spectral bandwidth for given spatial bandwidth */ mindiffavg = mindiffzeroavg = 0; avgdiffavg = 0; nvalid = 0; G_message(_("Estimating spectral bandwidth for spatial bandwidth %g..."), hspat); G_percent_reset(); for (row = globals->row_min; row < globals->row_max; row++) { G_percent(row - globals->row_min, globals->row_max - globals->row_min, 4); mwrow1 = row - radiusc; mwrow2 = mwrow1 + mwnrows; if (mwrow1 < globals->row_min) mwrow1 = globals->row_min; if (mwrow2 > globals->row_max) mwrow2 = globals->row_max; for (col = globals->col_min; col < globals->col_max; col++) { if ((FLAG_GET(globals->null_flag, row, col))) continue; /* get current band values */ Segment_get(globals->bands_in, (void *)Rin.mean, row, col); mwcol1 = col - radiusc; mwcol2 = mwcol1 + mwncols; if (mwcol1 < globals->col_min) mwcol1 = globals->col_min; if (mwcol2 > globals->col_max) mwcol2 = globals->col_max; /* get minimum spectral distance for this cell */ count = 0; mindiff = globals->max_diff; mindiffzero = globals->max_diff; avgdiff = 0; for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) { for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) { if ((FLAG_GET(globals->null_flag, mwrow, mwcol))) continue; if (mwrow == row && mwcol == col) continue; diff = mwrow - row; diff2 = diff * diff; diff = mwcol - col; diff2 += diff * diff; if (diff2 <= hspat2) { Segment_get(globals->bands_in, (void *)Rn.mean, mwrow, mwcol); /* get spectral distance */ diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals); if (mindiff > diff2) mindiff = diff2; if (mindiffzero > diff2 && diff2 > 0) mindiffzero = diff2; avgdiff += sqrt(diff2); count++; } } } if (count) { nvalid++; if (mindiff > 0) mindiffavg += sqrt(mindiff); mindiffzeroavg += sqrt(mindiffzero); if (avgdiff > 0) avgdiffavg += avgdiff / count; } } } G_percent(1, 1, 1); if (!nvalid) { G_fatal_error(_("Empty moving windows")); } mindiffavg /= nvalid; mindiffzeroavg /= nvalid; avgdiffavg /= nvalid; G_debug(1, "Average minimum difference to neighbours: %g", mindiffavg); G_debug(1, "Average minimum difference excl zero to neighbours: %g", mindiffzeroavg); G_debug(1, "Average average difference to neighbours: %g", avgdiffavg); /* use avgdiffavg as hspec for adaptive bandwidth */ hspec = globals->hr; if (hspec < 0 || hspec >= 1) { hspec = sqrt(avgdiffavg / 10.0); hspec = avgdiffavg; hspec = mindiffzeroavg; if (do_progressive) G_message(_("Initial range bandwidth: %g"), hspec); else G_message(_("Estimated range bandwidth: %g"), hspec); globals->hr = hspec; } else { G_message(_("Estimated range bandwidth: %g"), mindiffzeroavg); } if (do_adaptive) { /* bandwidth is now standard deviation for adaptive bandwidth * using a gaussian function with range bandwith used as * bandwidth for the gaussian function * the aim is to produce similar but improved results with * adaptive bandwidth * thus increase bandwidth */ hspec = sqrt(hspec); } hspec2 = hspec * hspec; sigmaspec2 = hspec2 / 9.; if (!do_progressive) { G_message(_("Spatial bandwidth: %g"), hspat); G_message(_("Range bandwidth: %g"), hspec); } G_debug(4, "Starting to process %ld candidate cells", globals->candidate_count); t = 0; n_changes = 1; maxdiff2 = 0; while (t < globals->end_t && n_changes > 0) { G_message(_("Processing pass %d..."), ++t); /* cells within an object should become more similar with each pass * therefore the spectral bandwidth could be decreased * and the spatial bandwidth could be increased */ /* spatial bandwidth: double the area covered by the moving window * area = M_PI * hspat * hspat * new hspat = sqrt(M_PI * hspat * hspat * 2 / M_PI) * no good, too large increases */ if (do_progressive) { if (t > 1) hspat *= 1.1; hspat2 = hspat * hspat; sigmaspat2 = hspat2 / 9.; radiusc = hspat; /* radius in cells truncated to integer */ mwnrows = mwncols = radiusc * 2 + 1; /* spectral bandwidth: reduce by 0.7 */ if (t > 1) hspec *= 0.9; hspec2 = hspec * hspec; sigmaspec2 = hspec2 / 9.; G_verbose_message(_("Spatial bandwidth: %g"), hspat); G_verbose_message(_("Range bandwidth: %g"), hspec); } n_changes = 0; maxdiff2 = 0; /* swap input and output */ seg_tmp = globals->bands_in; globals->bands_in = globals->bands_out; globals->bands_out = seg_tmp; /*process candidate cells */ G_percent_reset(); for (row = globals->row_min; row < globals->row_max; row++) { G_percent(row - globals->row_min, globals->row_max - globals->row_min, 4); mwrow1 = row - radiusc; mwrow2 = mwrow1 + mwnrows; if (mwrow1 < globals->row_min) mwrow1 = globals->row_min; if (mwrow2 > globals->row_max) mwrow2 = globals->row_max; for (col = globals->col_min; col < globals->col_max; col++) { if ((FLAG_GET(globals->null_flag, row, col))) continue; /* get current band values */ Segment_get(globals->bands_in, (void *)Rin.mean, row, col); /* init output */ for (n = 0; n < globals->nbands; n++) Rout.mean[n] = 0.; mwcol1 = col - radiusc; mwcol2 = mwcol1 + mwncols; if (mwcol1 < globals->col_min) mwcol1 = globals->col_min; if (mwcol2 > globals->col_max) mwcol2 = globals->col_max; hspecad2 = hspec2; if (do_adaptive) { /* adapt initial range bandwith */ ka2 = hspec2; /* OTB: conductance parameter */ avgdiff = 0; count = 0; for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) { for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) { if ((FLAG_GET(globals->null_flag, mwrow, mwcol))) continue; if (mwrow == row && mwcol == col) continue; diff = mwrow - row; diff2 = diff * diff; diff = mwcol - col; diff2 += diff * diff; if (diff2 <= hspat2) { Segment_get(globals->bands_in, (void *)Rn.mean, mwrow, mwcol); /* get spectral distance */ diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals); avgdiff += sqrt(diff2); count++; } } } hspecad2 = 0; if (avgdiff > 0) { avgdiff /= count; hspecad = hspec; /* OTB-like, contrast enhancing */ hspecad = exp(-avgdiff * avgdiff / (2 * ka2)) * avgdiff; /* preference for large regions, from Perona Malik 1990 * if the settings are right, it could be used to reduce noise */ /* hspecad = 1 / (1 + (avgdiff * avgdiff / (2 * hspec2))); */ hspecad2 = hspecad * hspecad; G_debug(1, "avg spectral diff: %g", avgdiff); G_debug(1, "initial hspec2: %g", hspec2); G_debug(1, "adapted hspec2: %g", hspecad2); } } /* actual mean shift */ wsum = 0; for (mwrow = mwrow1; mwrow < mwrow2; mwrow++) { for (mwcol = mwcol1; mwcol < mwcol2; mwcol++) { if ((FLAG_GET(globals->null_flag, mwrow, mwcol))) continue; diff = mwrow - row; diff2 = diff * diff; diff = mwcol - col; diff2 += diff * diff; if (diff2 <= hspat2) { w = 1; if (do_gauss) w = gauss_kernel(diff2, sigmaspat2); Segment_get(globals->bands_in, (void *)Rn.mean, mwrow, mwcol); /* check spectral distance */ diff2 = (globals->calculate_similarity)(&Rin, &Rn, globals); if (diff2 <= hspecad2) { if (do_gauss) w *= gauss_kernel(diff2, sigmaspec2); wsum += w; for (n = 0; n < globals->nbands; n++) Rout.mean[n] += w * Rn.mean[n]; } } } } if (wsum > 0) { for (n = 0; n < globals->nbands; n++) Rout.mean[n] /= wsum; } else { for (n = 0; n < globals->nbands; n++) Rout.mean[n] = Rin.mean[n]; } /* put new band values */ Segment_put(globals->bands_out, (void *)Rout.mean, row, col); /* if the squared difference between old and new band values * is larger than alpha2, then increase n_changes */ diff2 = (globals->calculate_similarity)(&Rin, &Rout, globals); if (diff2 > alpha2) n_changes++; if (maxdiff2 < diff2) maxdiff2 = diff2; } } G_percent(1, 1, 1); G_message(_("Changes > threshold: %d, largest change: %g"), n_changes, sqrt(maxdiff2)); } if (n_changes > 1) G_message(_("Mean shift stopped at %d due to reaching max iteration limit, more changes may be possible"), t); else G_message(_("Mean shift converged after %d iterations"), t); /* identify connected components */ cluster_bands(globals); /* remove small regions */ remove_small_clumps(globals); return TRUE; }
int init_vars(int argc, char *argv[]) { int r, c; int ele_fd, wat_fd, fd = -1; int seg_rows, seg_cols, num_cseg_total, num_open_segs, num_open_array_segs; double memory_divisor, heap_mem, seg_factor, disk_space; /* int page_block, num_cseg; */ int max_bytes; CELL *buf, alt_value, *alt_value_buf, block_value; char asp_value; DCELL wat_value; DCELL dvalue; WAT_ALT wa, *wabuf; ASP_FLAG af, af_nbr, *afbuf; char MASK_flag; void *elebuf, *ptr, *watbuf, *watptr; int ele_map_type, wat_map_type; size_t ele_size, wat_size; int ct_dir, r_nbr, c_nbr; G_gisinit(argv[0]); /* input */ ele_flag = pit_flag = run_flag = ril_flag = 0; /* output */ wat_flag = asp_flag = bas_flag = seg_flag = haf_flag = tci_flag = 0; bas_thres = 0; /* shed, unused */ arm_flag = dis_flag = 0; /* RUSLE */ ob_flag = st_flag = sl_flag = sg_flag = ls_flag = er_flag = 0; nxt_avail_pt = 0; /* dep_flag = 0; */ max_length = d_zero = 0.0; d_one = 1.0; ril_value = -1.0; /* dep_slope = 0.0; */ max_bytes = 0; sides = 8; mfd = 1; c_fac = 5; abs_acc = 0; ele_scale = 1; segs_mb = 300; /* scan options */ for (r = 1; r < argc; r++) { if (sscanf(argv[r], "elevation=%s", ele_name) == 1) ele_flag++; else if (sscanf(argv[r], "accumulation=%s", wat_name) == 1) wat_flag++; else if (sscanf(argv[r], "tci=%s", tci_name) == 1) tci_flag++; else if (sscanf(argv[r], "drainage=%s", asp_name) == 1) asp_flag++; else if (sscanf(argv[r], "depression=%s", pit_name) == 1) pit_flag++; else if (sscanf(argv[r], "threshold=%d", &bas_thres) == 1) ; else if (sscanf(argv[r], "max_slope_length=%lf", &max_length) == 1) ; else if (sscanf(argv[r], "basin=%s", bas_name) == 1) bas_flag++; else if (sscanf(argv[r], "stream=%s", seg_name) == 1) seg_flag++; else if (sscanf(argv[r], "half_basin=%s", haf_name) == 1) haf_flag++; else if (sscanf(argv[r], "flow=%s", run_name) == 1) run_flag++; else if (sscanf(argv[r], "ar=%s", arm_name) == 1) arm_flag++; /* slope length else if (sscanf(argv[r], "slope_length=%s", sl_name) == 1) sl_flag++; */ else if (sscanf(argv[r], "slope_steepness=%s", sg_name) == 1) sg_flag++; else if (sscanf(argv[r], "length_slope=%s", ls_name) == 1) ls_flag++; else if (sscanf(argv[r], "blocking=%s", ob_name) == 1) ob_flag++; else if (sscanf(argv[r], "memory=%lf", &segs_mb) == 1) ; else if (sscanf(argv[r], "disturbed_land=%s", ril_name) == 1) { if (sscanf(ril_name, "%lf", &ril_value) == 0) { ril_value = -1.0; ril_flag++; } } /* slope deposition else if (sscanf (argv[r], "sd=%[^\n]", dep_name) == 1) dep_flag++; */ else if (sscanf(argv[r], "-%d", &sides) == 1) { if (sides != 4) usage(argv[0]); } else if (sscanf(argv[r], "convergence=%d", &c_fac) == 1) ; else if (strcmp(argv[r], "-s") == 0) mfd = 0; else if (strcmp(argv[r], "-a") == 0) abs_acc = 1; else usage(argv[0]); } /* check options */ if (mfd == 1 && (c_fac < 1 || c_fac > 10)) { G_fatal_error("Convergence factor must be between 1 and 10."); } if ((ele_flag != 1) || ((arm_flag == 1) && ((bas_thres <= 0) || ((haf_flag != 1) && (bas_flag != 1)))) || ((bas_thres <= 0) && ((bas_flag == 1) || (seg_flag == 1) || (haf_flag == 1) || (sl_flag == 1) || (sg_flag == 1) || (ls_flag == 1))) ) usage(argv[0]); tot_parts = 4; if (sl_flag || sg_flag || ls_flag) er_flag = 1; /* do RUSLE */ if (er_flag) tot_parts++; /* define basins */ if (seg_flag || bas_flag || haf_flag) tot_parts++; G_message(_n("SECTION 1 beginning: Initiating Variables. %d section total.", "SECTION 1 beginning: Initiating Variables. %d sections total.", tot_parts), tot_parts); this_mapset = G_mapset(); /* for sd factor if (dep_flag) { if (sscanf (dep_name, "%lf", &dep_slope) != 1) { dep_flag = -1; } } */ G_get_set_window(&window); nrows = Rast_window_rows(); ncols = Rast_window_cols(); if (max_length <= d_zero) max_length = 10 * nrows * window.ns_res + 10 * ncols * window.ew_res; if (window.ew_res < window.ns_res) half_res = .5 * window.ew_res; else half_res = .5 * window.ns_res; diag = sqrt(window.ew_res * window.ew_res + window.ns_res * window.ns_res); if (sides == 4) diag *= 0.5; /* Segment rows and cols: 64 */ seg_rows = SROW; seg_cols = SCOL; /* seg_factor * <size in bytes> = segment size in KB */ seg_factor = seg_rows * seg_rows / 1024.; if (segs_mb < 3.0) { segs_mb = 3; G_warning(_("Maximum memory to be used was smaller than 3 MB," " set to 3 MB.")); } /* balance segment files */ /* elevation + accumulation: * 2 */ memory_divisor = sizeof(WAT_ALT) * 2; disk_space = sizeof(WAT_ALT); /* aspect and flags: * 4 */ memory_divisor += sizeof(ASP_FLAG) * 4; disk_space += sizeof(ASP_FLAG); /* astar_points: / 16 */ /* ideally only a few but large segments */ memory_divisor += sizeof(POINT) / 16.; disk_space += sizeof(POINT); /* heap points: / 4 */ memory_divisor += sizeof(HEAP_PNT) / 4.; disk_space += sizeof(HEAP_PNT); /* TCI: as is */ if (tci_flag) { memory_divisor += sizeof(double); disk_space += sizeof(double); } /* RUSLE */ if (er_flag) { /* r_h */ memory_divisor += 4; disk_space += 4; /* s_l */ memory_divisor += 8; disk_space += 8; /* s_g */ if (sg_flag) { memory_divisor += 8; disk_space += 8; } /* l_s */ if (ls_flag) { memory_divisor += 8; disk_space += 8; } /* ril */ if (ril_flag) { memory_divisor += 8; disk_space += 8; } } /* KB -> MB */ memory_divisor = memory_divisor * seg_factor / 1024.; disk_space = disk_space * seg_factor / 1024.; num_open_segs = segs_mb / memory_divisor; heap_mem = num_open_segs * seg_factor * sizeof(HEAP_PNT) / (4. * 1024.); G_debug(1, "segs MB: %.0f", segs_mb); G_debug(1, "region rows: %d", nrows); G_debug(1, "seg rows: %d", seg_rows); G_debug(1, "region cols: %d", ncols); G_debug(1, "seg cols: %d", seg_cols); num_cseg_total = nrows / SROW + 1; G_debug(1, " row segments:\t%d", num_cseg_total); num_cseg_total = ncols / SCOL + 1; G_debug(1, "column segments:\t%d", num_cseg_total); num_cseg_total = (ncols / seg_cols + 1) * (nrows / seg_rows + 1); G_debug(1, " total segments:\t%d", num_cseg_total); G_debug(1, " open segments:\t%d", num_open_segs); /* nonsense to have more segments open than exist */ if (num_open_segs > num_cseg_total) num_open_segs = num_cseg_total; G_debug(1, " open segments after adjusting:\t%d", num_open_segs); disk_space *= num_cseg_total; if (disk_space < 1024.0) G_verbose_message(_("Will need up to %.2f MB of disk space"), disk_space); else G_verbose_message(_("Will need up to %.2f GB (%.0f MB) of disk space"), disk_space / 1024.0, disk_space); if (er_flag) { cseg_open(&r_h, seg_rows, seg_cols, num_open_segs); cseg_read_cell(&r_h, ele_name, ""); } /* read elevation input and mark NULL/masked cells */ /* scattered access: alt, watalt, bitflags, asp */ seg_open(&watalt, nrows, ncols, seg_rows, seg_cols, num_open_segs * 2, sizeof(WAT_ALT)); seg_open(&aspflag, nrows, ncols, seg_rows, seg_cols, num_open_segs * 4, sizeof(ASP_FLAG)); if (tci_flag) dseg_open(&tci, seg_rows, seg_cols, num_open_segs); /* open elevation input */ ele_fd = Rast_open_old(ele_name, ""); ele_map_type = Rast_get_map_type(ele_fd); ele_size = Rast_cell_size(ele_map_type); elebuf = Rast_allocate_buf(ele_map_type); afbuf = G_malloc(ncols * sizeof(ASP_FLAG)); if (ele_map_type == FCELL_TYPE || ele_map_type == DCELL_TYPE) ele_scale = 1000; /* should be enough to do the trick */ /* initial flow accumulation */ if (run_flag) { wat_fd = Rast_open_old(run_name, ""); wat_map_type = Rast_get_map_type(ele_fd); wat_size = Rast_cell_size(ele_map_type); watbuf = Rast_allocate_buf(ele_map_type); } else { watbuf = watptr = NULL; wat_fd = wat_size = wat_map_type = -1; } wabuf = G_malloc(ncols * sizeof(WAT_ALT)); alt_value_buf = Rast_allocate_buf(CELL_TYPE); /* read elevation input and mark NULL/masked cells */ G_message("SECTION 1a: Mark masked and NULL cells"); MASK_flag = 0; do_points = (GW_LARGE_INT) nrows * ncols; for (r = 0; r < nrows; r++) { G_percent(r, nrows, 1); Rast_get_row(ele_fd, elebuf, r, ele_map_type); ptr = elebuf; if (run_flag) { Rast_get_row(wat_fd, watbuf, r, wat_map_type); watptr = watbuf; } for (c = 0; c < ncols; c++) { afbuf[c].flag = 0; afbuf[c].asp = 0; /* check for masked and NULL cells */ if (Rast_is_null_value(ptr, ele_map_type)) { FLAG_SET(afbuf[c].flag, NULLFLAG); FLAG_SET(afbuf[c].flag, INLISTFLAG); FLAG_SET(afbuf[c].flag, WORKEDFLAG); Rast_set_c_null_value(&alt_value, 1); /* flow accumulation */ Rast_set_d_null_value(&wat_value, 1); do_points--; } else { if (ele_map_type == CELL_TYPE) { alt_value = *((CELL *)ptr); } else if (ele_map_type == FCELL_TYPE) { dvalue = *((FCELL *)ptr); dvalue *= ele_scale; alt_value = ele_round(dvalue); } else if (ele_map_type == DCELL_TYPE) { dvalue = *((DCELL *)ptr); dvalue *= ele_scale; alt_value = ele_round(dvalue); } /* flow accumulation */ if (run_flag) { if (Rast_is_null_value(watptr, wat_map_type)) { wat_value = 0; /* ok ? */ } else { if (wat_map_type == CELL_TYPE) { wat_value = *((CELL *)watptr); } else if (wat_map_type == FCELL_TYPE) { wat_value = *((FCELL *)watptr); } else if (wat_map_type == DCELL_TYPE) { wat_value = *((DCELL *)watptr); } } } else { wat_value = 1; } } wabuf[c].wat = wat_value; wabuf[c].ele = alt_value; alt_value_buf[c] = alt_value; ptr = G_incr_void_ptr(ptr, ele_size); if (run_flag) { watptr = G_incr_void_ptr(watptr, wat_size); } } seg_put_row(&watalt, (char *) wabuf, r); seg_put_row(&aspflag, (char *)afbuf, r); if (er_flag) { cseg_put_row(&r_h, alt_value_buf, r); } } G_percent(nrows, nrows, 1); /* finish it */ Rast_close(ele_fd); G_free(wabuf); G_free(afbuf); if (run_flag) { Rast_close(wat_fd); G_free(watbuf); } MASK_flag = (do_points < nrows * ncols); /* do RUSLE */ if (er_flag) { if (ob_flag) { fd = Rast_open_old(ob_name, ""); buf = Rast_allocate_c_buf(); for (r = 0; r < nrows; r++) { G_percent(r, nrows, 1); Rast_get_c_row(fd, buf, r); for (c = 0; c < ncols; c++) { block_value = buf[c]; if (!Rast_is_c_null_value(&block_value) && block_value) { seg_get(&aspflag, (char *)&af, r, c); FLAG_SET(af.flag, RUSLEBLOCKFLAG); seg_put(&aspflag, (char *)&af, r, c); } } } G_percent(nrows, nrows, 1); /* finish it */ Rast_close(fd); G_free(buf); } if (ril_flag) { dseg_open(&ril, seg_rows, seg_cols, num_open_segs); dseg_read_cell(&ril, ril_name, ""); } /* dseg_open(&slp, SROW, SCOL, num_open_segs); */ dseg_open(&s_l, seg_rows, seg_cols, num_open_segs); if (sg_flag) dseg_open(&s_g, seg_rows, seg_cols, num_open_segs); if (ls_flag) dseg_open(&l_s, seg_rows, seg_cols, num_open_segs); } G_debug(1, "open segments for A* points"); /* columns per segment */ seg_cols = seg_rows * seg_rows; num_cseg_total = do_points / seg_cols; if (do_points % seg_cols > 0) num_cseg_total++; /* no need to have more segments open than exist */ num_open_array_segs = num_open_segs / 16.; if (num_open_array_segs > num_cseg_total) num_open_array_segs = num_cseg_total; if (num_open_array_segs < 1) num_open_array_segs = 1; seg_open(&astar_pts, 1, do_points, 1, seg_cols, num_open_array_segs, sizeof(POINT)); /* one-based d-ary search_heap with astar_pts */ G_debug(1, "open segments for A* search heap"); G_debug(1, "heap memory %.2f MB", heap_mem); /* columns per segment */ /* larger is faster */ seg_cols = seg_rows * seg_rows; num_cseg_total = do_points / seg_cols; if (do_points % seg_cols > 0) num_cseg_total++; /* no need to have more segments open than exist */ num_open_array_segs = (1 << 20) * heap_mem / (seg_cols * sizeof(HEAP_PNT)); if (num_open_array_segs > num_cseg_total) num_open_array_segs = num_cseg_total; if (num_open_array_segs < 2) num_open_array_segs = 2; G_debug(1, "A* search heap open segments %d, total %d", num_open_array_segs, num_cseg_total); /* the search heap will not hold more than 5% of all points at any given time ? */ /* chances are good that the heap will fit into one large segment */ seg_open(&search_heap, 1, do_points + 1, 1, seg_cols, num_open_array_segs, sizeof(HEAP_PNT)); G_message(_("SECTION 1b: Determining Offmap Flow.")); /* heap is empty */ heap_size = 0; if (pit_flag) { buf = Rast_allocate_c_buf(); fd = Rast_open_old(pit_name, ""); } else buf = NULL; first_astar = first_cum = -1; for (r = 0; r < nrows; r++) { G_percent(r, nrows, 1); if (pit_flag) Rast_get_c_row(fd, buf, r); for (c = 0; c < ncols; c++) { seg_get(&aspflag, (char *)&af, r, c); if (!FLAG_GET(af.flag, NULLFLAG)) { if (er_flag) dseg_put(&s_l, &half_res, r, c); asp_value = af.asp; if (r == 0 || c == 0 || r == nrows - 1 || c == ncols - 1) { /* dseg_get(&wat, &wat_value, r, c); */ seg_get(&watalt, (char *)&wa, r, c); wat_value = wa.wat; if (wat_value > 0) { wat_value = -wat_value; /* dseg_put(&wat, &wat_value, r, c); */ wa.wat = wat_value; seg_put(&watalt, (char *)&wa, r, c); } if (r == 0) asp_value = -2; else if (c == 0) asp_value = -4; else if (r == nrows - 1) asp_value = -6; else if (c == ncols - 1) asp_value = -8; /* cseg_get(&alt, &alt_value, r, c); */ alt_value = wa.ele; add_pt(r, c, alt_value); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, EDGEFLAG); af.asp = asp_value; seg_put(&aspflag, (char *)&af, r, c); } else { seg_get(&watalt, (char *)&wa, r, c); for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; seg_get(&aspflag, (char *)&af_nbr, r_nbr, c_nbr); if (FLAG_GET(af_nbr.flag, NULLFLAG)) { af.asp = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; add_pt(r, c, wa.ele); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, EDGEFLAG); seg_put(&aspflag, (char *)&af, r, c); wat_value = wa.wat; if (wat_value > 0) { wa.wat = -wat_value; seg_put(&watalt, (char *)&wa, r, c); } break; } } } /* real depression ? */ if (pit_flag && asp_value == 0) { if (!Rast_is_c_null_value(&buf[c]) && buf[c] != 0) { seg_get(&watalt, (char *)&wa, r, c); add_pt(r, c, wa.ele); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, EDGEFLAG); seg_put(&aspflag, (char *)&af, r, c); wat_value = wa.wat; if (wat_value > 0) { wa.wat = -wat_value; seg_put(&watalt, (char *)&wa, r, c); } } } } /* end non-NULL cell */ } /* end column */ } G_percent(r, nrows, 1); /* finish it */ return 0; }
static int read_seed(struct globals *globals, SEGMENT *seeds_seg, struct rc *Ri, int new_id) { int n, i, Ri_id, Rk_id; struct rc ngbr_rc, next; struct rclist rilist; int neighbors[8][2]; G_debug(4, "read_seed()"); /* get Ri's segment ID from input seeds */ Segment_get(seeds_seg, &Ri_id, Ri->row, Ri->col); /* set new segment id */ if (Segment_put(&globals->rid_seg, &new_id, Ri->row, Ri->col) != 1) G_fatal_error(_("Unable to write to temporary file")); /* set candidate flag */ FLAG_SET(globals->candidate_flag, Ri->row, Ri->col); /* initialize region stats */ globals->rs.count = 1; globals->rs.id = new_id; Segment_get(&globals->bands_seg, (void *)globals->bands_val, Ri->row, Ri->col); for (i = 0; i < globals->nbands; i++) { globals->rs.sum[i] = globals->bands_val[i]; globals->rs.mean[i] = globals->bands_val[i]; } /* go through seed, spreading outwards from head */ rclist_init(&rilist); rclist_add(&rilist, Ri->row, Ri->col); while (rclist_drop(&rilist, &next)) { G_debug(5, "find_pixel_neighbors for row: %d , col %d", next.row, next.col); globals->find_neighbors(next.row, next.col, neighbors); for (n = 0; n < globals->nn; n++) { ngbr_rc.row = neighbors[n][0]; ngbr_rc.col = neighbors[n][1]; if (ngbr_rc.row < 0 || ngbr_rc.row >= globals->nrows || ngbr_rc.col < 0 || ngbr_rc.col >= globals->ncols) { continue; } if (FLAG_GET(globals->null_flag, ngbr_rc.row, ngbr_rc.col)) { continue; } if (FLAG_GET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col)) { continue; } Segment_get(seeds_seg, (void *) &Rk_id, ngbr_rc.row, ngbr_rc.col); G_debug(5, "Rk ID = %d Ri ID = %d", Rk_id, Ri_id); if (Rk_id != Ri_id) { continue; } /* set segment id */ if (Segment_put(&globals->rid_seg, &new_id, ngbr_rc.row, ngbr_rc.col) != 1) G_fatal_error(_("Unable to write to temporary file")); /* set candidate flag */ FLAG_SET(globals->candidate_flag, ngbr_rc.row, ngbr_rc.col); /* add to list of cells to check */ rclist_add(&rilist, ngbr_rc.row, ngbr_rc.col); /* update region stats */ Segment_get(&globals->bands_seg, (void *)globals->bands_val, ngbr_rc.row, ngbr_rc.col); for (i = 0; i < globals->nbands; i++) { globals->rs.sum[i] += globals->bands_val[i]; } globals->rs.count++; } } if (rgtree_find(globals->reg_tree, &(globals->rs)) != NULL) { G_fatal_error(_("Segment %d is already registered!"), new_id); } /* insert into region tree */ if (globals->rs.count >= globals->min_reg_size) { for (i = 0; i < globals->nbands; i++) globals->rs.mean[i] = globals->rs.sum[i] / globals->rs.count; rgtree_insert(globals->reg_tree, &(globals->rs)); } else { if (globals->rs.count > 1) update_band_vals(Ri->row, Ri->col, &(globals->rs), globals); } if (globals->rs.count > 1) globals->n_regions -= (globals->rs.count - 1); return 1; }
static int load_seeds(struct globals *globals, int srows, int scols, int nseg) { int row, col; SEGMENT seeds_seg; CELL *seeds_buf, seeds_val; int seeds_fd; int spos, sneg, have_seeds; struct rc Ri; G_debug(1, "load_seeds()"); G_message(_("Loading seeds from raster map <%s>..."), globals->seeds); if (Segment_open (&seeds_seg, G_tempfile(), globals->nrows, globals->ncols, srows, scols, sizeof(CELL), nseg) != TRUE) G_fatal_error("Unable to create bounds temporary files"); seeds_fd = Rast_open_old(globals->seeds, ""); seeds_buf = Rast_allocate_c_buf(); have_seeds = 0; /* load seeds map to segment structure */ for (row = 0; row < globals->nrows; row++) { Rast_get_c_row(seeds_fd, seeds_buf, row); for (col = 0; col < globals->ncols; col++) { if (FLAG_GET(globals->null_flag, row, col)) { Rast_set_c_null_value(&seeds_val, 1); } else { seeds_val = seeds_buf[col]; if (!Rast_is_c_null_value(&seeds_val)) have_seeds = 1; } if (Segment_put(&seeds_seg, &seeds_val, row, col) != 1) G_fatal_error(_("Unable to write to temporary file")); } } if (!have_seeds) { G_warning(_("No seeds found in '%s'!"), globals->seeds); G_free(seeds_buf); Rast_close(seeds_fd); Segment_close(&seeds_seg); return 0; } spos = 1; sneg = -1; /* convert seeds to regions */ G_debug(1, "convert seeds to regions"); Rast_set_c_null_value(&seeds_val, 1); for (row = 0; row < globals->nrows; row++) { Rast_get_c_row(seeds_fd, seeds_buf, row); for (col = 0; col < globals->ncols; col++) { if (!(FLAG_GET(globals->null_flag, row, col)) && !(FLAG_GET(globals->candidate_flag, row, col))) { if (Rast_is_c_null_value(&(seeds_buf[col]))) { if (Segment_put(&globals->rid_seg, &sneg, row, col) != 1) G_fatal_error(_("Unable to write to temporary file")); sneg--; globals->n_regions--; } else { Ri.row = row; Ri.col = col; read_seed(globals, &seeds_seg, &Ri, spos); spos++; } } } } G_free(seeds_buf); Rast_close(seeds_fd); Segment_close(&seeds_seg); globals->n_regions = spos - 1; flag_clear_all(globals->candidate_flag); return 1; }
int open_files(struct globals *globals) { struct Ref Ref; /* group reference list */ int *in_fd, bounds_fd, is_null; int n, row, col, srows, scols, inlen, outlen, nseg; DCELL **inbuf; /* buffers to store lines from each of the imagery group rasters */ CELL *boundsbuf, bounds_val; int have_bounds = 0; CELL s, id; struct Range range; /* min/max values of bounds map */ struct FPRange *fp_range; /* min/max values of each input raster */ DCELL *min, *max; struct ngbr_stats Ri, Rk; /*allocate memory for flags */ globals->null_flag = flag_create(globals->nrows, globals->ncols); globals->candidate_flag = flag_create(globals->nrows, globals->ncols); flag_clear_all(globals->null_flag); flag_clear_all(globals->candidate_flag); G_debug(1, "Checking image group..."); /* ****** open the input rasters ******* */ if (!I_get_group_ref(globals->image_group, &Ref)) G_fatal_error(_("Group <%s> not found in the current mapset"), globals->image_group); if (Ref.nfiles <= 0) G_fatal_error(_("Group <%s> contains no raster maps"), globals->image_group); /* Read Imagery Group */ in_fd = G_malloc(Ref.nfiles * sizeof(int)); inbuf = (DCELL **) G_malloc(Ref.nfiles * sizeof(DCELL *)); fp_range = G_malloc(Ref.nfiles * sizeof(struct FPRange)); min = G_malloc(Ref.nfiles * sizeof(DCELL)); max = G_malloc(Ref.nfiles * sizeof(DCELL)); G_debug(1, "Opening input rasters..."); for (n = 0; n < Ref.nfiles; n++) { inbuf[n] = Rast_allocate_d_buf(); in_fd[n] = Rast_open_old(Ref.file[n].name, Ref.file[n].mapset); } /* Get min/max values of each input raster for scaling */ globals->max_diff = 0.; globals->nbands = Ref.nfiles; for (n = 0; n < Ref.nfiles; n++) { /* returns -1 on error, 2 on empty range, quitting either way. */ if (Rast_read_fp_range(Ref.file[n].name, Ref.file[n].mapset, &fp_range[n]) != 1) G_fatal_error(_("No min/max found in raster map <%s>"), Ref.file[n].name); Rast_get_fp_range_min_max(&(fp_range[n]), &min[n], &max[n]); G_debug(1, "Range for layer %d: min = %f, max = %f", n, min[n], max[n]); } if (globals->weighted == FALSE) globals->max_diff = Ref.nfiles; else { /* max difference with selected similarity method */ Ri.mean = max; Rk.mean = min; globals->max_diff = 1; globals->max_diff = (*globals->calculate_similarity) (&Ri, &Rk, globals); } /* ********** find out file segmentation size ************ */ G_debug(1, "Calculate temp file sizes..."); /* size of each element to be stored */ inlen = sizeof(DCELL) * Ref.nfiles; outlen = sizeof(CELL); G_debug(1, "data element size, in: %d , out: %d ", inlen, outlen); globals->datasize = sizeof(double) * globals->nbands; /* count non-null cells */ globals->notnullcells = (long)globals->nrows * globals->ncols; for (row = 0; row < globals->nrows; row++) { for (n = 0; n < Ref.nfiles; n++) { Rast_get_d_row(in_fd[n], inbuf[n], row); } for (col = 0; col < globals->ncols; col++) { is_null = 0; /*Assume there is data */ for (n = 0; n < Ref.nfiles; n++) { if (Rast_is_d_null_value(&inbuf[n][col])) { is_null = 1; } } if (is_null) { globals->notnullcells--; FLAG_SET(globals->null_flag, row, col); } } } G_verbose_message(_("Non-NULL cells: %ld"), globals->notnullcells); if (globals->notnullcells < 2) G_fatal_error(_("Insufficient number of non-NULL cells in current region")); /* segment lib segment size */ srows = 64; scols = 64; nseg = manage_memory(srows, scols, globals); /* create segment structures */ if (Segment_open (&globals->bands_seg, G_tempfile(), globals->nrows, globals->ncols, srows, scols, inlen, nseg) != 1) G_fatal_error("Unable to create input temporary files"); if (Segment_open (&globals->rid_seg, G_tempfile(), globals->nrows, globals->ncols, srows, scols, outlen, nseg * 2) != 1) G_fatal_error("Unable to create input temporary files"); /* load input bands to segment structure */ if (Ref.nfiles > 1) G_message(_("Loading input bands...")); else G_message(_("Loading input band...")); globals->bands_val = (double *)G_malloc(inlen); globals->second_val = (double *)G_malloc(inlen); /* initial segment ID */ s = 1; globals->row_min = globals->nrows; globals->row_max = 0; globals->col_min = globals->ncols; globals->col_max = 0; for (row = 0; row < globals->nrows; row++) { G_percent(row, globals->nrows, 4); for (n = 0; n < Ref.nfiles; n++) { Rast_get_d_row(in_fd[n], inbuf[n], row); } for (col = 0; col < globals->ncols; col++) { is_null = 0; /*Assume there is data */ for (n = 0; n < Ref.nfiles; n++) { globals->bands_val[n] = inbuf[n][col]; if (Rast_is_d_null_value(&inbuf[n][col])) { is_null = 1; } else { if (globals->weighted == FALSE) /* scaled version */ globals->bands_val[n] = (inbuf[n][col] - min[n]) / (max[n] - min[n]); } } if (Segment_put(&globals->bands_seg, (void *)globals->bands_val, row, col) != 1) G_fatal_error(_("Unable to write to temporary file")); if (!is_null) { if (!globals->seeds) { /* sequentially number all cells with a unique segment ID */ id = s; s++; } /* get min/max row/col to narrow the processing window */ if (globals->row_min > row) globals->row_min = row; if (globals->row_max < row) globals->row_max = row; if (globals->col_min > col) globals->col_min = col; if (globals->col_max < col) globals->col_max = col; } else { /* all input bands NULL */ Rast_set_c_null_value(&id, 1); FLAG_SET(globals->null_flag, row, col); } if (!globals->seeds || is_null) { if (Segment_put(&globals->rid_seg, (void *)&id, row, col) != 1) G_fatal_error(_("Unable to write to temporary file")); } } } G_percent(1, 1, 1); G_debug(1, "nrows: %d, min row: %d, max row %d", globals->nrows, globals->row_min, globals->row_max); G_debug(1, "ncols: %d, min col: %d, max col %d", globals->ncols, globals->col_min, globals->col_max); globals->row_max++; globals->col_max++; globals->ncells = (long)(globals->row_max - globals->row_min) * (globals->col_max - globals->col_min); /* bounds/constraints */ Rast_set_c_null_value(&globals->upper_bound, 1); Rast_set_c_null_value(&globals->lower_bound, 1); if (globals->bounds_map != NULL) { if (Segment_open (&globals->bounds_seg, G_tempfile(), globals->nrows, globals->ncols, srows, scols, sizeof(CELL), nseg) != TRUE) G_fatal_error("Unable to create bounds temporary files"); if (Rast_read_range(globals->bounds_map, globals->bounds_mapset, &range) != 1) G_fatal_error(_("No min/max found in raster map <%s>"), globals->bounds_map); Rast_get_range_min_max(&range, &globals->upper_bound, &globals->lower_bound); if (Rast_is_c_null_value(&globals->upper_bound) || Rast_is_c_null_value(&globals->lower_bound)) { G_fatal_error(_("No min/max found in raster map <%s>"), globals->bounds_map); } bounds_fd = Rast_open_old(globals->bounds_map, globals->bounds_mapset); boundsbuf = Rast_allocate_c_buf(); for (row = 0; row < globals->nrows; row++) { Rast_get_c_row(bounds_fd, boundsbuf, row); for (col = 0; col < globals->ncols; col++) { bounds_val = boundsbuf[col]; if (FLAG_GET(globals->null_flag, row, col)) { Rast_set_c_null_value(&bounds_val, 1); } else { if (!Rast_is_c_null_value(&bounds_val)) { have_bounds = 1; if (globals->lower_bound > bounds_val) globals->lower_bound = bounds_val; if (globals->upper_bound < bounds_val) globals->upper_bound = bounds_val; } } if (Segment_put(&globals->bounds_seg, &bounds_val, row, col) != 1) G_fatal_error(_("Unable to write to temporary file")); } } Rast_close(bounds_fd); G_free(boundsbuf); if (!have_bounds) { G_warning(_("There are no boundary constraints in '%s'"), globals->bounds_map); Rast_set_c_null_value(&globals->upper_bound, 1); Rast_set_c_null_value(&globals->lower_bound, 1); Segment_close(&globals->bounds_seg); globals->bounds_map = NULL; globals->bounds_mapset = NULL; } } else { G_debug(1, "no boundary constraint supplied."); } /* other info */ globals->candidate_count = 0; /* counter for remaining candidate pixels */ /* Free memory */ for (n = 0; n < Ref.nfiles; n++) { G_free(inbuf[n]); Rast_close(in_fd[n]); } globals->rs.sum = G_malloc(globals->datasize); globals->rs.mean = G_malloc(globals->datasize); globals->reg_tree = rgtree_create(globals->nbands, globals->datasize); globals->n_regions = s - 1; if (globals->seeds) { load_seeds(globals, srows, scols, nseg); } G_debug(1, "Number of initial regions: %d", globals->n_regions); G_free(inbuf); G_free(in_fd); G_free(fp_range); G_free(min); G_free(max); return TRUE; }
int do_cum(void) { int r, c, dr, dc; int r_nbr, c_nbr, ct_dir, np_side, edge; CELL is_swale, aspect, ele_nbr; DCELL value, valued; int killer, threshold; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; int this_index, down_index, nbr_index; double *dist_to_nbr, *contour; double cell_size; G_message(_("SECTION 3: Accumulating Surface Flow with SFD.")); /* distances to neighbours, contour lengths */ dist_to_nbr = (double *)G_malloc(sides * sizeof(double)); contour = (double *)G_malloc(sides * sizeof(double)); cell_size = get_dist(dist_to_nbr, contour); if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; aspect = asp[this_index]; seg_index_rc(alt_seg, this_index, &r, &c); if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } /* skip user-defined depressions */ else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ down_index = SEG_INDEX(wat_seg, dr, dc); value = wat[this_index]; if (fabs(value) >= threshold) FLAG_SET(swale, r, c); valued = wat[down_index]; edge = 0; np_side = -1; for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; if (dr == r_nbr && dc == c_nbr) np_side = ct_dir; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); ele_nbr = alt[nbr_index]; if (Rast_is_c_null_value(&ele_nbr)) edge = 1; } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { is_swale = FLAG_GET(swale, r, c); if (is_swale && aspect > 0) { aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; asp[this_index] = aspect; } if (valued > 0) wat[down_index] = -valued; continue; } if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wat[down_index] = valued; /* topographic wetness index ln(a / tan(beta)) and * stream power index a * tan(beta) */ if (atanb_flag) { sca[this_index] = fabs(wat[this_index]) * (cell_size / contour[np_side]); tanb[this_index] = get_slope_tci(alt[this_index], alt[down_index], dist_to_nbr[np_side]); } is_swale = FLAG_GET(swale, r, c); if (is_swale || fabs(valued) >= threshold) { FLAG_SET(swale, dr, dc); } else { if (er_flag && !is_swale) slope_length(r, c, dr, dc); } } } G_free(astar_pts); return 0; }
int do_astar(void) { int doer, count; int upr, upc, r = -1, c = -1, ct_dir; CELL alt_val, alt_nbr[8]; WAT_ALT wa; char asp_val; char flag_value, is_in_list, is_worked; HEAP_PNT heap_p; /* sides * |7|1|4| * |2| |3| * |5|0|6| */ int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 }; int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 }; double dx, dy, dist_to_nbr[8], ew_res, ns_res; double slope[8]; int skip_diag; int count_edge = 0, count_diag = 0, count_edge_sink = 0, count_diag_sink = 0; G_message(_("SECTION 2: A* Search.")); for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for neighbours */ upr = nextdr[ct_dir]; upc = nextdc[ct_dir]; /* account for rare cases when ns_res != ew_res */ dy = ABS(upr) * window.ns_res; dx = ABS(upc) * window.ew_res; if (ct_dir < 4) dist_to_nbr[ct_dir] = dx + dy; else dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy); } ew_res = window.ew_res; ns_res = window.ns_res; if (heap_size == 0) G_fatal_error(_("No seeds for A* Search")); G_debug(1, "heap size %d, points %d", heap_size, do_points); count = 0; doer = do_points - 1; /* A* Search: search uphill, get downhill paths */ while (heap_size > 0) { G_percent(count++, do_points, 1); heap_p = drop_pt(); r = heap_p.pnt.r; c = heap_p.pnt.c; G_debug(3, "heap size %d, r %d, c %d", heap_size, r, c); alt_val = heap_p.ele; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; slope[ct_dir] = alt_nbr[ct_dir] = 0; /* check if upr, upc are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { bseg_get(&bitflags, &flag_value, upr, upc); is_in_list = FLAG_GET(flag_value, INLISTFLAG); is_worked = FLAG_GET(flag_value, WORKEDFLAG); skip_diag = 0; /* avoid diagonal flow direction bias */ if (!is_worked) { seg_get(&watalt, (char *)&wa, upr, upc); alt_nbr[ct_dir] = wa.ele; slope[ct_dir] = get_slope2(alt_val, alt_nbr[ct_dir], dist_to_nbr[ct_dir]); } if (!is_in_list) { if (ct_dir > 3 && slope[ct_dir] > 0) { if (slope[nbr_ew[ct_dir]] > 0) { /* slope to ew nbr > slope to center */ if (slope[ct_dir] < get_slope2(alt_nbr[nbr_ew[ct_dir]], alt_nbr[ct_dir], ew_res)) skip_diag = 1; } if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) { /* slope to ns nbr > slope to center */ if (slope[ct_dir] < get_slope2(alt_nbr[nbr_ns[ct_dir]], alt_nbr[ct_dir], ns_res)) skip_diag = 1; } } } /* add neighbour as new point if not in the list */ if (is_in_list == 0 && skip_diag == 0) { /* set flow direction */ asp_val = drain[upr - r + 1][upc - c + 1]; add_pt(upr, upc, alt_nbr[ct_dir]); bseg_put(&asp, &asp_val, upr, upc); FLAG_SET(flag_value, INLISTFLAG); bseg_put(&bitflags, &flag_value, upr, upc); if (alt_nbr[ct_dir] < alt_val) { if (ct_dir < 4) count_edge_sink++; else count_diag_sink++; } /* includes flat areas */ else { if (ct_dir < 4) count_edge++; else count_diag++; } } else if (is_in_list && is_worked == 0 && FLAG_GET(flag_value, EDGEFLAG)) { /* neighbour is edge in list, not yet worked */ bseg_get(&asp, &asp_val, upr, upc); if (asp_val < 0) { /* adjust flow direction for edge cell */ asp_val = drain[upr - r + 1][upc - c + 1]; bseg_put(&asp, &asp_val, upr, upc); seg_get(&watalt, (char *)&wa, r, c); if (wa.wat > 0) { wa.wat = -wa.wat; seg_put(&watalt, (char *)&wa, r, c); } } /* neighbour is inside real depression, not yet worked */ else if (asp_val == 0) { asp_val = drain[upr - r + 1][upc - c + 1]; bseg_put(&asp, &asp_val, upr, upc); } } } } /* add astar points to sorted list for flow accumulation */ seg_put(&astar_pts, (char *)&heap_p.pnt, 0, doer); doer--; bseg_get(&bitflags, &flag_value, r, c); FLAG_SET(flag_value, WORKEDFLAG); bseg_put(&bitflags, &flag_value, r, c); } if (doer != -1) G_fatal_error(_("bug in A* Search: doer %d heap size %d count %d"), doer, heap_size, count); seg_close(&search_heap); G_percent(count, do_points, 1); /* finish it */ G_debug(1, "edge direction: %d (%.2f%%)", count_edge, (double) 100. * count_edge / (count_edge + count_diag)); G_debug(1, "diag direction: %d (%.2f%%)", count_diag, (double) 100. * count_diag / (count_edge + count_diag)); G_debug(1, "edge out of depression: %d (%.2f%%)", count_edge_sink, (double) 100. * count_edge_sink / (count_edge_sink + count_diag_sink)); G_debug(1, "diag out of depression: %d (%.2f%%)", count_diag_sink, (double) 100. * count_diag_sink / (count_edge_sink + count_diag_sink)); return 0; }
int remove_small_clumps(struct globals *globals) { int row, col, i; struct NB_TREE *nbtree; int this_id; struct ngbr_stats *Rbest; int best_n_id, best_n_row, best_n_col; int reg_size; CELL *renumber, n_regions, min_rid; /* two possible modes * best (most similar) neighbor * neighbor with longest shared boundary */ if (globals->min_segment_size < 2) return 0; G_message(_("Merging segments smaller than %d cells..."), globals->min_segment_size); /* init renumber */ renumber = (CELL *) G_malloc(sizeof(CELL) * (globals->max_rid + 1)); for (i = 0; i <= globals->max_rid; i++) renumber[i] = 0; /* clear candidate flag */ flag_clear_all(globals->candidate_flag); min_rid = globals->max_rid; /* Set candidate flag to true/1 for all non-NULL cells */ for (row = globals->row_min; row < globals->row_max; row++) { for (col = globals->col_min; col < globals->col_max; col++) { if (!(FLAG_GET(globals->null_flag, row, col))) { FLAG_SET(globals->candidate_flag, row, col); Segment_get(&globals->rid_seg, (void *) &this_id, row, col); /* renumber is region size */ if (renumber[this_id] <= globals->min_segment_size) { renumber[this_id]++; if (min_rid > this_id) min_rid = this_id; } } } } min_rid--; nbtree = nbtree_create(globals->nbands, globals->datasize); /* go through all cells */ G_percent_reset(); for (row = globals->row_min; row < globals->row_max; row++) { G_percent(row - globals->row_min, globals->row_max - globals->row_min, 2); for (col = globals->col_min; col < globals->col_max; col++) { if ((FLAG_GET(globals->null_flag, row, col))) continue; if (!(FLAG_GET(globals->candidate_flag, row, col))) continue; /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); reg_size = renumber[this_id]; best_n_id = 1; while (reg_size < globals->min_segment_size && best_n_id > 0) { Rbest = NULL; reg_size = 1; best_n_row = best_n_col = -1; best_n_id = find_best_neighbour(globals, row, col, this_id, nbtree, ®_size, &Rbest, &best_n_row, &best_n_col); /* Rbest: pointer to most common neighbour * best_n_id, best_n_[row|col]: most similar neighbour */ if (reg_size < globals->min_segment_size && best_n_id > 0) { /* update rid */ update_rid(globals, row, col, best_n_id); /* mark as merged */ renumber[best_n_id] += renumber[this_id]; reg_size = renumber[best_n_id]; renumber[this_id] = 0; this_id = best_n_id; } } } } G_percent(1, 1, 1); n_regions = 0; /* renumber becomes new region ID */ for (i = 1; i <= globals->max_rid; i++) { if (renumber[i] > 0) { renumber[i] = ++n_regions; } } G_message(_("Renumbering remaining %d segments..."), n_regions); for (row = globals->row_min; row < globals->row_max; row++) { G_percent(row - globals->row_min, globals->row_max - globals->row_min, 4); for (col = globals->col_min; col < globals->col_max; col++) { if ((FLAG_GET(globals->null_flag, row, col))) continue; /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); if (Rast_is_c_null_value(&this_id) || this_id < 1) continue; this_id = renumber[this_id] + min_rid; Segment_put(&globals->rid_seg, (void *) &this_id, row, col); } } G_percent(1, 1, 1); globals->max_rid = n_regions + min_rid; G_free(renumber); nbtree_clear(nbtree); return 1; }
int init_search(int depr_fd) { int r, c, r_nbr, c_nbr, ct_dir; CELL *depr_buf, ele_value; int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 }; int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 }; char asp_value, is_null; WAT_ALT wa; ASP_FLAG af, af_nbr; GW_LARGE_INT n_depr_cells = 0; nxt_avail_pt = heap_size = 0; /* load edge cells and real depressions to A* heap */ if (depr_fd >= 0) depr_buf = Rast_allocate_buf(CELL_TYPE); else depr_buf = NULL; G_message(_("Initializing A* search...")); for (r = 0; r < nrows; r++) { G_percent(r, nrows, 2); if (depr_fd >= 0) { Rast_get_row(depr_fd, depr_buf, r, CELL_TYPE); } for (c = 0; c < ncols; c++) { seg_get(&aspflag, (char *)&af, r, c); is_null = FLAG_GET(af.flag, NULLFLAG); if (is_null) continue; asp_value = 0; if (r == 0 || r == nrows - 1 || c == 0 || c == ncols - 1) { if (r == 0 && c == 0) asp_value = -7; else if (r == 0 && c == ncols - 1) asp_value = -5; else if (r == nrows - 1 && c == 0) asp_value = -1; else if (r == nrows - 1 && c == ncols - 1) asp_value = -3; else if (r == 0) asp_value = -2; else if (c == 0) asp_value = -4; else if (r == nrows - 1) asp_value = -6; else if (c == ncols - 1) asp_value = -8; seg_get(&watalt, (char *)&wa, r, c); ele_value = wa.ele; heap_add(r, c, ele_value); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, EDGEFLAG); af.asp = asp_value; seg_put(&aspflag, (char *)&af, r, c); continue; } /* any neighbour NULL ? */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; seg_get(&aspflag, (char *)&af_nbr, r_nbr, c_nbr); is_null = FLAG_GET(af_nbr.flag, NULLFLAG); if (is_null) { asp_value = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; seg_get(&watalt, (char *)&wa, r, c); ele_value = wa.ele; heap_add(r, c, ele_value); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, EDGEFLAG); af.asp = asp_value; seg_put(&aspflag, (char *)&af, r, c); break; } } if (asp_value) /* some neighbour was NULL, point added to list */ continue; /* real depression ? */ if (depr_fd >= 0) { if (!Rast_is_c_null_value(&depr_buf[c]) && depr_buf[c] != 0) { seg_get(&watalt, (char *)&wa, r, c); ele_value = wa.ele; heap_add(r, c, ele_value); FLAG_SET(af.flag, INLISTFLAG); FLAG_SET(af.flag, DEPRFLAG); af.asp = asp_value; seg_put(&aspflag, (char *)&af, r, c); n_depr_cells++; } } } } G_percent(nrows, nrows, 2); /* finish it */ if (depr_fd >= 0) { Rast_close(depr_fd); G_free(depr_buf); } G_debug(1, "%lld edge cells", heap_size - n_depr_cells); if (n_depr_cells) G_debug(1, "%lld cells in depressions", n_depr_cells); return 1; }
int do_cum_mfd(void) { int r, c, dr, dc; DCELL value, valued, *wat_nbr; POINT point; WAT_ALT wa; int killer, threshold; /* MFD */ int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null; double *dist_to_nbr, *weight, sum_weight, max_weight; int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side, max_side; double dx, dy; CELL ele, *ele_nbr; char asp_val, asp_val_down; double prop, max_acc; int workedon, edge, is_swale, flat; char *flag_nbr, this_flag_value, flag_value; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; G_message(_("SECTION 3: Accumulating Surface Flow with MFD.")); G_debug(1, "MFD convergence factor set to %d.", c_fac); /* distances to neighbours */ dist_to_nbr = (double *)G_malloc(sides * sizeof(double)); weight = (double *)G_malloc(sides * sizeof(double)); for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = nextdr[ct_dir]; c_nbr = nextdc[ct_dir]; /* account for rare cases when ns_res != ew_res */ dy = ABS(r_nbr) * window.ns_res; dx = ABS(c_nbr) * window.ew_res; if (ct_dir < 4) dist_to_nbr[ct_dir] = dx + dy; else dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy); } flag_nbr = (char *)G_malloc(sides * sizeof(char)); wat_nbr = (DCELL *)G_malloc(sides * sizeof(DCELL)); ele_nbr = (CELL *)G_malloc(sides * sizeof(CELL)); workedon = 0; if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 0; killer < do_points; killer++) { G_percent(killer, do_points, 1); seg_get(&astar_pts, (char *)&point, 0, killer); r = point.r; c = point.c; bseg_get(&asp, &asp_val, r, c); if (asp_val) { dr = r + asp_r[ABS(asp_val)]; dc = c + asp_c[ABS(asp_val)]; } /* skip user-defined depressions */ else dr = dc = -1; /* WORKEDFLAG has been set during A* Search * reversed meaning here: 0 = done, 1 = not yet done */ bseg_get(&bitflags, &this_flag_value, r, c); FLAG_UNSET(this_flag_value, WORKEDFLAG); if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { r_max = dr; c_max = dc; seg_get(&watalt, (char *)&wa, r, c); value = wa.wat; /* get weights */ max_weight = 0; sum_weight = 0; np_side = -1; mfd_cells = 0; stream_cells = 0; swale_cells = 0; astar_not_set = 1; ele = wa.ele; is_null = 0; edge = 0; flat = 1; /* this loop is needed to get the sum of weights */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; weight[ct_dir] = -1; wat_nbr[ct_dir] = 0; ele_nbr[ct_dir] = 0; /* check if neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { if (dr == r_nbr && dc == c_nbr) np_side = ct_dir; bseg_get(&bitflags, &flag_nbr[ct_dir], r_nbr, c_nbr); seg_get(&watalt, (char *)&wa, r_nbr, c_nbr); wat_nbr[ct_dir] = wa.wat; ele_nbr[ct_dir] = wa.ele; /* check for swale or stream cells */ is_swale = FLAG_GET(flag_nbr[ct_dir], SWALEFLAG); if (is_swale) swale_cells++; if ((ABS(wat_nbr[ct_dir]) + 0.5) >= threshold && ct_dir != np_side && ele_nbr[ct_dir] > ele) stream_cells++; if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) { if (ele_nbr[ct_dir] != ele) flat = 0; edge = is_null = FLAG_GET(flag_nbr[ct_dir], NULLFLAG); if (!is_null && ele_nbr[ct_dir] <= ele) { if (ele_nbr[ct_dir] < ele) { weight[ct_dir] = mfd_pow(((ele - ele_nbr[ct_dir]) / dist_to_nbr[ct_dir]), c_fac); } if (ele_nbr[ct_dir] == ele) { weight[ct_dir] = mfd_pow((0.5 / dist_to_nbr[ct_dir]), c_fac); } sum_weight += weight[ct_dir]; mfd_cells++; if (weight[ct_dir] > max_weight) { max_weight = weight[ct_dir]; } if (dr == r_nbr && dc == c_nbr) { astar_not_set = 0; } } } } else edge = 1; if (edge) break; } /* do not continue streams along edges, this causes artifacts */ if (edge) { is_swale = FLAG_GET(this_flag_value, SWALEFLAG); if (is_swale && asp_val > 0) { asp_val = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; bseg_put(&asp, &asp_val, r, c); } bseg_put(&bitflags, &this_flag_value, r, c); continue; } /* honour A * path * mfd_cells == 0: fine, SFD along A * path * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells */ /* MFD, A * path not included, add to mfd_cells */ if (mfd_cells > 0 && astar_not_set == 1) { mfd_cells++; sum_weight += max_weight; weight[np_side] = max_weight; max_side = np_side; } /* set flow accumulation for neighbours */ max_acc = -1; max_side = np_side; if (mfd_cells > 1) { prop = 0.0; for (ct_dir = 0; ct_dir < sides; ct_dir++) { r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; /* check if neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols && weight[ct_dir] > -0.5) { if (FLAG_GET(flag_nbr[ct_dir], WORKEDFLAG)) { weight[ct_dir] = weight[ct_dir] / sum_weight; /* check everything adds up to 1.0 */ prop += weight[ct_dir]; if (value > 0) { if (wat_nbr[ct_dir] > 0) wat_nbr[ct_dir] += value * weight[ct_dir]; else wat_nbr[ct_dir] -= value * weight[ct_dir]; } else { if (wat_nbr[ct_dir] < 0) wat_nbr[ct_dir] += value * weight[ct_dir]; else wat_nbr[ct_dir] = value * weight[ct_dir] - wat_nbr[ct_dir]; } valued = wat_nbr[ct_dir]; wa.wat = valued; wa.ele = ele_nbr[ct_dir]; seg_put(&watalt, (char *)&wa, r_nbr, c_nbr); /* get main drainage direction */ if (ABS(wat_nbr[ct_dir]) >= max_acc) { max_acc = ABS(wat_nbr[ct_dir]); r_max = r_nbr; c_max = c_nbr; max_side = ct_dir; } } else if (ct_dir == np_side) { /* check for consistency with A * path */ workedon++; } } } /* adjust main drainage direction to A* path if possible */ /*if (fabs(wat_nbr[np_side]) >= max_acc) { max_acc = fabs(wat_nbr[np_side]); r_max = dr; c_max = dc; } */ if (ABS(prop - 1.0) > 5E-6f) { G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"), prop); } } /* SFD-like accumulation */ else { valued = wat_nbr[np_side]; if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wa.wat = valued; wa.ele = ele_nbr[np_side]; seg_put(&watalt, (char *)&wa, dr, dc); } /* update asp */ if (dr != r_max || dc != c_max) { if (asp_val < 0) { asp_val = -1 * drain[r - r_max + 1][c - c_max + 1]; } else asp_val = drain[r - r_max + 1][c - c_max + 1]; bseg_put(&asp, &asp_val, r, c); } is_swale = FLAG_GET(this_flag_value, SWALEFLAG); /* start new stream */ value = ABS(value) + 0.5; if (!is_swale && (int)value >= threshold && stream_cells < 1 && swale_cells < 1 && !flat) { FLAG_SET(this_flag_value, SWALEFLAG); is_swale = 1; } /* continue stream */ if (is_swale) { flag_value = flag_nbr[max_side]; FLAG_SET(flag_value, SWALEFLAG); bseg_put(&bitflags, &flag_value, r_max, c_max); } else { if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG)) slope_length(r, c, r_max, c_max); } } bseg_put(&bitflags, &this_flag_value, r, c); } G_percent(do_points, do_points, 1); /* finish it */ if (workedon) G_warning(_("MFD: A * path already processed when distributing flow: %d of %d cells"), workedon, do_points); seg_close(&astar_pts); G_free(dist_to_nbr); G_free(weight); G_free(wat_nbr); G_free(ele_nbr); G_free(flag_nbr); return 0; }
void* rsys_render(void* ptr) { /* I didn't want to use any locks in here, but it's impossible without. So ... one lock is needed for the queue, and one for the flags of the renderer. */ struct rsys* rsys = ptr; /* make ctt1 the context for this thread */ if(rsys->table.ctt1_make != NULL) rsys->table.ctt1_make(); int running = 1; while(running) { frame_begin(&rsys->frame); /* ### FRAME BEGIN ### */ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ACCUM_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glClearColor(rsys->bg_red, rsys->bg_green, rsys->bg_blue, 1.0f); /* read from rsys instead of this */ //glUseProgram(rsys->vsh); //glUseProgram(rsys->fsh); /* pull one request from queue per frame */ rsys_req_t* req = NULL; ocn_spin_lock(&rsys->render_reqs_lock); queue_pull(&rsys->render_reqs, (void*)&req); ocn_spin_unlock(&rsys->render_reqs_lock); /* Requests with token equal to 0 are NOT! treated special. The request struct uses a flag field now ... */ if(req != NULL) { if(FLAG_GET(req->flags, RSYS_REQ_RENDERER)) { switch(req->type) { case RSYS_REQ_TYPE_QUIT: running = 0; break; case RSYS_REQ_TYPE_BG: break; case RSYS_REQ_TYPE_ADD: /* add to render list */ break; default: break; } } } LIST_FOREACH_BEGIN(&rsys->ros) ro_entity_t* ro = LIST_ENTRY_DATA; if(req != NULL) { if(!FLAG_GET(req->flags, RSYS_REQ_RENDERER)) { if(ro->token == req->token) { switch(req->type) { case RSYS_REQ_TYPE_DEL: break; case RSYS_REQ_TYPE_MAP: break; case RSYS_REQ_TYPE_UNMAP: break; default: break; } } } } /* call render function */ /* switch(ro->type) { case RO_TYPE_STATIC_MESH: ro_static_mesh_render(&ro->static_mesh); break; default: break; } */ LIST_FOREACH_END // bad idea... but for now we leave this like this // we could make a second queue for cleaning up requests free(req); if(rsys->table.win_swap != NULL) rsys->table.win_swap(); /* call frame callback */ //if(ocn.funcs.frame_callback != NULL) // ocn.funcs.frame_callback(0); /* ### FRAME END ### */ frame_wait(&rsys->frame); frame_end (&rsys->frame); frame_calc(&rsys->frame); } return NULL; }
int do_cum_mfd(void) { int r, c, dr, dc; CELL is_swale; DCELL value, valued, tci_div, sum_contour, cell_size; int killer, threshold; /* MFD */ int mfd_cells, stream_cells, swale_cells, astar_not_set, is_null; double *dist_to_nbr, *contour, *weight, sum_weight, max_weight; int r_nbr, c_nbr, r_max, c_max, ct_dir, np_side; CELL ele, ele_nbr, aspect, is_worked; double prop, max_val; int workedon, edge, flat; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; int this_index, down_index, nbr_index; G_message(_("SECTION 3a: Accumulating Surface Flow with MFD.")); G_debug(1, "MFD convergence factor set to %d.", c_fac); /* distances to neighbours, weights, contour lengths */ dist_to_nbr = (double *)G_malloc(sides * sizeof(double)); weight = (double *)G_malloc(sides * sizeof(double)); contour = (double *)G_malloc(sides * sizeof(double)); cell_size = get_dist(dist_to_nbr, contour); flag_clear_all(worked); workedon = 0; if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; seg_index_rc(alt_seg, this_index, &r, &c); FLAG_SET(worked, r, c); aspect = asp[this_index]; if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ value = wat[this_index]; down_index = SEG_INDEX(wat_seg, dr, dc); /* get weights */ max_weight = 0; sum_weight = 0; np_side = -1; mfd_cells = 0; astar_not_set = 1; ele = alt[this_index]; is_null = 0; edge = 0; /* this loop is needed to get the sum of weights */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; weight[ct_dir] = -1; if (dr == r_nbr && dc == c_nbr) np_side = ct_dir; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); valued = wat[nbr_index]; ele_nbr = alt[nbr_index]; is_worked = FLAG_GET(worked, r_nbr, c_nbr); if (is_worked == 0) { is_null = Rast_is_c_null_value(&ele_nbr); edge = is_null; if (!is_null && ele_nbr <= ele) { if (ele_nbr < ele) { weight[ct_dir] = mfd_pow(((ele - ele_nbr) / dist_to_nbr[ct_dir]), c_fac); } if (ele_nbr == ele) { weight[ct_dir] = mfd_pow((0.5 / dist_to_nbr[ct_dir]), c_fac); } sum_weight += weight[ct_dir]; mfd_cells++; if (weight[ct_dir] > max_weight) { max_weight = weight[ct_dir]; } if (dr == r_nbr && dc == c_nbr) { astar_not_set = 0; } if (value < 0 && valued > 0) wat[nbr_index] = -valued; } } } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { continue; } /* honour A * path * mfd_cells == 0: fine, SFD along A * path * mfd_cells == 1 && astar_not_set == 0: fine, SFD along A * path * mfd_cells > 0 && astar_not_set == 1: A * path not included, add to mfd_cells */ /* MFD, A * path not included, add to mfd_cells */ if (mfd_cells > 0 && astar_not_set == 1) { mfd_cells++; sum_weight += max_weight; weight[np_side] = max_weight; } /* set flow accumulation for neighbours */ max_val = -1; tci_div = sum_contour = 0.; if (mfd_cells > 1) { prop = 0.0; for (ct_dir = 0; ct_dir < sides; ct_dir++) { r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols && weight[ct_dir] > -0.5) { is_worked = FLAG_GET(worked, r_nbr, c_nbr); if (is_worked == 0) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); weight[ct_dir] = weight[ct_dir] / sum_weight; /* check everything adds up to 1.0 */ prop += weight[ct_dir]; if (atanb_flag) { sum_contour += contour[ct_dir]; tci_div += get_slope_tci(ele, alt[nbr_index], dist_to_nbr[ct_dir]) * weight[ct_dir]; } valued = wat[nbr_index]; if (value > 0) { if (valued > 0) valued += value * weight[ct_dir]; else valued -= value * weight[ct_dir]; } else { if (valued < 0) valued += value * weight[ct_dir]; else valued = value * weight[ct_dir] - valued; } wat[nbr_index] = valued; } else if (ct_dir == np_side) { /* check for consistency with A * path */ workedon++; } } } if (ABS(prop - 1.0) > 5E-6f) { G_warning(_("MFD: cumulative proportion of flow distribution not 1.0 but %f"), prop); } } /* SFD-like accumulation */ else { valued = wat[down_index]; if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wat[down_index] = valued; if (atanb_flag) { sum_contour = contour[np_side]; tci_div = get_slope_tci(ele, alt[down_index], dist_to_nbr[np_side]); } } /* topographic wetness index ln(a / tan(beta)) and * stream power index a * tan(beta) */ if (atanb_flag) { sca[this_index] = fabs(wat[this_index]) * (cell_size / sum_contour); tanb[this_index] = tci_div; } } } if (workedon) G_warning(n_("MFD: A * path already processed when distributing flow: %d of %d cell", "MFD: A * path already processed when distributing flow: %d of %d cells", do_points), workedon, do_points); G_message(_("SECTION 3b: Adjusting drainage directions.")); for (killer = 1; killer <= do_points; killer++) { G_percent(killer, do_points, 1); this_index = astar_pts[killer]; seg_index_rc(alt_seg, this_index, &r, &c); FLAG_UNSET(worked, r, c); aspect = asp[this_index]; if (aspect) { dr = r + asp_r[ABS(aspect)]; dc = c + asp_c[ABS(aspect)]; } else dr = dc = -1; if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* if ((dr = astar_pts[killer].downr) > -1) { */ value = wat[this_index]; down_index = SEG_INDEX(wat_seg, dr, dc); r_max = dr; c_max = dc; /* get max flow accumulation */ max_val = -1; stream_cells = 0; swale_cells = 0; ele = alt[this_index]; is_null = 0; edge = 0; flat = 1; for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; /* check that neighbour is within region */ if (r_nbr >= 0 && r_nbr < nrows && c_nbr >= 0 && c_nbr < ncols) { nbr_index = SEG_INDEX(wat_seg, r_nbr, c_nbr); /* check for swale or stream cells */ is_swale = FLAG_GET(swale, r_nbr, c_nbr); if (is_swale) swale_cells++; valued = wat[nbr_index]; ele_nbr = alt[nbr_index]; edge = Rast_is_c_null_value(&ele_nbr); if ((ABS(valued) + 0.5) >= threshold && ele_nbr > ele) stream_cells++; is_worked = !(FLAG_GET(worked, r_nbr, c_nbr)); if (is_worked == 0) { if (ele_nbr != ele) flat = 0; is_null = Rast_is_c_null_value(&ele_nbr); edge = is_null; if (!is_null && ABS(valued) > max_val) { max_val = ABS(valued); r_max = r_nbr; c_max = c_nbr; } } } else edge = 1; if (edge) break; } /* do not distribute flow along edges, this causes artifacts */ if (edge) { is_swale = FLAG_GET(swale, r, c); if (is_swale && aspect > 0) { aspect = -1 * drain[r - r_nbr + 1][c - c_nbr + 1]; asp[this_index] = aspect; } continue; } /* update asp */ if (dr != r_max || dc != c_max) { aspect = drain[r - r_max + 1][c - c_max + 1]; if (asp[this_index] < 0) aspect = -aspect; asp[this_index] = aspect; } is_swale = FLAG_GET(swale, r, c); /* start new stream */ value = ABS(value) + 0.5; if (!is_swale && (int)value >= threshold && stream_cells < 1 && swale_cells < 1 && !flat) { FLAG_SET(swale, r, c); is_swale = 1; } /* continue stream */ if (is_swale) { FLAG_SET(swale, r_max, c_max); } else { if (er_flag && !is_swale) slope_length(r, c, r_max, c_max); } } } G_free(astar_pts); flag_destroy(worked); G_free(dist_to_nbr); G_free(weight); return 0; }
static int check_reg_size(struct globals *globals, int minsize, int row, int col) { int rown, coln, n; int neighbors[8][2]; int this_id; int ngbr_id; LARGEINT reg_size; struct RB_TREE *visited; struct rc next, ngbr_rc; struct rclist rilist; int no_check; if (!(FLAG_GET(globals->candidate_flag, row, col))) return minsize; FLAG_UNSET(globals->candidate_flag, row, col); visited = rbtree_create(cmp_rc, sizeof(struct rc)); ngbr_rc.row = row; ngbr_rc.col = col; rbtree_insert(visited, &ngbr_rc); /* get this ID */ Segment_get(&globals->rid_seg, (void *) &this_id, row, col); /* breadth-first search */ next.row = row; next.col = col; rclist_init(&rilist); reg_size = 1; do { globals->find_neighbors(next.row, next.col, neighbors); n = globals->nn - 1; do { rown = neighbors[n][0]; coln = neighbors[n][1]; no_check = 0; if (rown < globals->row_min || rown >= globals->row_max || coln < globals->col_min || coln >= globals->col_max) no_check = 1; if (!no_check && (FLAG_GET(globals->null_flag, rown, coln))) no_check = 1; ngbr_rc.row = rown; ngbr_rc.col = coln; if (!no_check && !rbtree_find(visited, &ngbr_rc)) { rbtree_insert(visited, &ngbr_rc); /* get neighbour ID */ Segment_get(&globals->rid_seg, (void *) &ngbr_id, rown, coln); /* same neighbour */ if (ngbr_id == this_id) { reg_size++; rclist_add(&rilist, rown, coln); FLAG_UNSET(globals->candidate_flag, rown, coln); } } } while (n--); /* end do loop - next neighbor */ } while (rclist_drop(&rilist, &next)); /* while there are cells to check */ rclist_destroy(&rilist); rbtree_destroy(visited); return reg_size; }
int close_array_seg(void) { struct Colors colors; int incr, max, red, green, blue, rd, gr, bl, flag; int c, r, map_fd; CELL *cellrow, value; CELL *theseg; RAMSEG thesegseg; cellrow = Rast_allocate_c_buf(); if (seg_flag || bas_flag || haf_flag) { if (seg_flag) { theseg = bas; thesegseg = bas_seg; } else if (bas_flag) { theseg = bas; thesegseg = bas_seg; } else { theseg = haf; thesegseg = haf_seg; } max = n_basins; G_debug(1, "%d basins created", max); Rast_init_colors(&colors); if (max > 0) Rast_make_random_colors(&colors, 1, max); else { G_warning(_("No basins were created. Verify threshold and region settings.")); Rast_make_random_colors(&colors, 1, 2); } if (max < 1000 && max > 0) { Rast_set_c_color((CELL) 0, 0, 0, 0, &colors); r = 1; incr = 0; while (incr >= 0) { G_percent(r, max, 2); for (gr = 130 + incr; gr <= 255; gr += 20) { for (rd = 90 + incr; rd <= 255; rd += 30) { for (bl = 90 + incr; bl <= 255; bl += 40) { flag = 1; while (flag) { Rast_get_c_color(&r, &red, &green, &blue, &colors); /* if existing rule is too dark then append a new rule to override it */ if ((blue * .11 + red * .30 + green * .59) < 100) { Rast_set_c_color(r, rd, gr, bl, &colors); flag = 0; } if (++r > max) { gr = rd = bl = 300; flag = 0; incr = -1; } } } } } if (incr >= 0) { incr += 15; if (incr > 120) incr = 7; } } G_percent(r - 1, max, 3); /* finish it */ } else G_debug(1, "Too many subbasins to reasonably check for color brightness"); /* using the existing stack of while/for/for/for/while loops ... */ } /* stream segments map */ if (seg_flag) { map_fd = Rast_open_c_new(seg_name); for (r = 0; r < nrows; r++) { Rast_set_c_null_value(cellrow, ncols); /* reset row to all NULL */ for (c = 0; c < ncols; c++) { value = FLAG_GET(swale, r, c); if (value) cellrow[c] = bas[SEG_INDEX(bas_seg, r, c)]; } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(seg_name, this_mapset, &colors); } /* basins map */ if (bas_flag) { map_fd = Rast_open_c_new(bas_name); for (r = 0; r < nrows; r++) { for (c = 0; c < ncols; c++) { cellrow[c] = bas[SEG_INDEX(bas_seg, r, c)]; if (cellrow[c] == 0) Rast_set_c_null_value(cellrow + c, 1); } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(bas_name, this_mapset, &colors); } /* half_basins map */ if (haf_flag) { map_fd = Rast_open_c_new(haf_name); for (r = 0; r < nrows; r++) { for (c = 0; c < ncols; c++) { cellrow[c] = haf[SEG_INDEX(haf_seg, r, c)]; if (cellrow[c] == 0) Rast_set_c_null_value(cellrow + c, 1); } Rast_put_row(map_fd, cellrow, CELL_TYPE); } Rast_close(map_fd); Rast_write_colors(haf_name, this_mapset, &colors); } if (seg_flag || bas_flag || haf_flag) Rast_free_colors(&colors); G_free(haf); G_free(bas); G_free(cellrow); if (arm_flag) fclose(fp); close_maps(); return 0; }
int do_cum(void) { int r, c, dr, dc; char asp_val, asp_val_down; char is_swale, this_flag_value, flag_value; DCELL value, valued; POINT point; int killer, threshold; int asp_r[9] = { 0, -1, -1, -1, 0, 1, 1, 1, 0 }; int asp_c[9] = { 0, 1, 0, -1, -1, -1, 0, 1, 1 }; WAT_ALT wa, wadown; G_message(_("SECTION 3: Accumulating Surface Flow with SFD.")); if (bas_thres <= 0) threshold = 60; else threshold = bas_thres; for (killer = 0; killer < do_points; killer++) { G_percent(killer, do_points, 1); seg_get(&astar_pts, (char *)&point, 0, killer); r = point.r; c = point.c; bseg_get(&asp, &asp_val, r, c); if (asp_val) { dr = r + asp_r[ABS(asp_val)]; dc = c + asp_c[ABS(asp_val)]; } /* skip user-defined depressions */ else dr = dc = -1; bseg_get(&bitflags, &this_flag_value, r, c); FLAG_UNSET(this_flag_value, WORKEDFLAG); if (dr >= 0 && dr < nrows && dc >= 0 && dc < ncols) { /* TODO: do not distribute flow along edges, this causes artifacts */ seg_get(&watalt, (char *)&wa, r, c); value = wa.wat; is_swale = FLAG_GET(this_flag_value, SWALEFLAG); if (fabs(value) >= threshold && !is_swale) { is_swale = 1; FLAG_SET(this_flag_value, SWALEFLAG); } seg_get(&watalt, (char *)&wadown, dr, dc); valued = wadown.wat; if (value > 0) { if (valued > 0) valued += value; else valued -= value; } else { if (valued < 0) valued += value; else valued = value - valued; } wadown.wat = valued; seg_put(&watalt, (char *)&wadown, dr, dc); /* update asp for depression */ if (is_swale || fabs(valued) >= threshold) { bseg_get(&bitflags, &flag_value, dr, dc); FLAG_SET(flag_value, SWALEFLAG); bseg_put(&bitflags, &flag_value, dr, dc); is_swale = 1; } else { if (er_flag && !is_swale && !FLAG_GET(this_flag_value, RUSLEBLOCKFLAG)) slope_length(r, c, dr, dc); } } bseg_put(&bitflags, &this_flag_value, r, c); } G_percent(do_points, do_points, 1); /* finish it */ seg_close(&astar_pts); return 0; }
/* * return 0 if nothing was modidied * return 1 if elevation was modified */ int do_flatarea(int index, CELL ele, CELL *alt_org, CELL *alt_new) { int upr, upc, r, c, ct_dir; CELL is_in_list, is_worked, this_in_list; int index_doer, index_up; int n_flat_cells = 0, counter; CELL ele_nbr, min_ele_diff; int uphill_order, downhill_order, max_uphill_order, max_downhill_order; int last_order; struct pq *up_pq = pq_create(); struct pq *down_pq = pq_create(); struct orders inc_order, *order_found, *nbr_order_found; struct RB_TREE *order_tree = rbtree_create(cmp_orders, sizeof(struct orders)); pq_add(index, down_pq); pq_add(index, up_pq); inc_order.downhill = -1; inc_order.uphill = 0; inc_order.index = index; inc_order.flag = 0; rbtree_insert(order_tree, &inc_order); n_flat_cells = 1; min_ele_diff = INT_MAX; max_uphill_order = max_downhill_order = 0; /* get uphill start points */ G_debug(2, "get uphill start points"); counter = 0; while (down_pq->size) { if ((index_doer = pq_drop(down_pq)) == -1) G_fatal_error("get start points: no more points in down queue"); seg_index_rc(alt_seg, index_doer, &r, &c); FLAG_SET(flat_done, r, c); /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.downhill = -1; inc_order.uphill = -1; inc_order.index = index_up; inc_order.flag = 0; /* not yet added to queue */ if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) { n_flat_cells++; /* add to down queue if not yet in there */ pq_add(index_up, down_pq); /* add to up queue if not yet in there */ if (is_in_list) { pq_add(index_up, up_pq); /* set uphill order to 0 */ inc_order.uphill = 0; counter++; } rbtree_insert(order_tree, &inc_order); } } } } } /* flat area too small, not worth the effort */ if (n_flat_cells < 5) { /* clean up */ pq_destroy(up_pq); pq_destroy(down_pq); rbtree_destroy(order_tree); return 0; } G_debug(2, "%d flat cells, %d cells in tree, %d start cells", n_flat_cells, (int)order_tree->count, counter); pq_destroy(down_pq); down_pq = pq_create(); /* got uphill start points, do uphill correction */ G_debug(2, "got uphill start points, do uphill correction"); counter = 0; uphill_order = 1; while (up_pq->size) { int is_in_down_queue = 0; if ((index_doer = pq_drop(up_pq)) == -1) G_fatal_error("uphill order: no more points in up queue"); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get uphill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for uphill correction")); last_order = uphill_order - 1; uphill_order = order_found->uphill; if (last_order > uphill_order) G_warning(_("queue error: last uphill order %d > current uphill order %d"), last_order, uphill_order); /* debug */ if (uphill_order == -1) G_fatal_error(_("uphill order not set")); if (max_uphill_order < uphill_order) max_uphill_order = uphill_order; uphill_order++; counter++; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; /* all cells that are in_list should have been added * previously as uphill start points */ if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) { G_fatal_error(_("flat cell escaped in uphill correction")); } /* not yet added to queue */ if (nbr_order_found->uphill == -1) { if (is_in_list) G_warning("cell should be in queue"); /* add to up queue */ pq_add(index_up, up_pq); /* set nbr uphill order = current uphill order + 1 */ nbr_order_found->uphill = uphill_order; } } /* add focus cell to down queue */ if (!this_in_list && !is_in_down_queue && ele_nbr != ele && !is_in_list && !is_worked) { pq_add(index_doer, down_pq); /* set downhill order to 0 */ order_found->downhill = 0; is_in_down_queue = 1; } if (ele_nbr > ele && min_ele_diff > ele_nbr - ele) min_ele_diff = ele_nbr - ele; } } } /* debug: all flags should be set to 0 */ pq_destroy(up_pq); up_pq = pq_create(); /* got downhill start points, do downhill correction */ G_debug(2, "got downhill start points, do downhill correction"); downhill_order = 1; while (down_pq->size) { if ((index_doer = pq_drop(down_pq)) == -1) G_fatal_error(_("downhill order: no more points in down queue")); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get downhill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for downhill correction")); last_order = downhill_order - 1; downhill_order = order_found->downhill; if (last_order > downhill_order) G_warning(_("queue error: last downhill order %d > current downhill order %d"), last_order, downhill_order); /* debug */ if (downhill_order == -1) G_fatal_error(_("downhill order: downhill order not set")); if (max_downhill_order < downhill_order) max_downhill_order = downhill_order; downhill_order++; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped in downhill correction")); /* not yet added to queue */ if (nbr_order_found->downhill == -1) { /* add to down queue */ pq_add(index_up, down_pq); /* set nbr downhill order = current downhill order + 1 */ nbr_order_found->downhill = downhill_order; /* add to up queue */ if (is_in_list) { pq_add(index_up, up_pq); /* set flag */ nbr_order_found->flag = 1; } } } } } } /* got uphill and downhill order, adjust ele */ /* increment: ele += uphill_order + max_downhill_order - downhill_order */ /* decrement: ele += uphill_order - max_uphill_order - downhill_order */ G_debug(2, "adjust ele"); while (up_pq->size) { if ((index_doer = pq_drop(up_pq)) == -1) G_fatal_error("no more points in up queue"); seg_index_rc(alt_seg, index_doer, &r, &c); this_in_list = FLAG_GET(in_list, r, c); /* get uphill and downhill order for this point */ inc_order.index = index_doer; if ((order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped for adjustment")); uphill_order = order_found->uphill; downhill_order = order_found->downhill; /* debug */ if (uphill_order == -1) G_fatal_error(_("adjustment: uphill order not set")); if (!this_in_list && downhill_order == -1) G_fatal_error(_("adjustment: downhill order not set")); /* increment */ if (this_in_list) { downhill_order = max_downhill_order; uphill_order = 0; } alt_new[index_doer] += (uphill_order + (double)(max_downhill_order - downhill_order) / 2.0 + 0.5) / 2.0 + 0.5; /* check all neighbours, breadth first search */ for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (upr, upc) for this neighbour */ upr = r + nextdr[ct_dir]; upc = c + nextdc[ct_dir]; /* check if r, c are within region */ if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) { index_up = SEG_INDEX(alt_seg, upr, upc); is_in_list = FLAG_GET(in_list, upr, upc); is_worked = FLAG_GET(worked, upr, upc); ele_nbr = alt_org[index_up]; if (ele_nbr == ele && !is_worked) { inc_order.index = index_up; if ((nbr_order_found = rbtree_find(order_tree, &inc_order)) == NULL) G_fatal_error(_("flat cell escaped in adjustment")); /* not yet added to queue */ if (nbr_order_found->flag == 0) { if (is_in_list) G_warning("adjustment: in_list cell should be in queue"); /* add to up queue */ pq_add(index_up, up_pq); nbr_order_found->flag = 1; } } } } } /* clean up */ pq_destroy(up_pq); pq_destroy(down_pq); rbtree_destroy(order_tree); return 1; }
int do_astar(void) { int r, c, r_nbr, c_nbr, ct_dir; GW_LARGE_INT first_cum, count; int nextdr[8] = { 1, -1, 0, 0, -1, 1, 1, -1 }; int nextdc[8] = { 0, 0, -1, 1, 1, -1, 1, -1 }; CELL ele_val, ele_up, ele_nbr[8]; WAT_ALT wa; ASP_FLAG af; char is_in_list, is_worked; HEAP_PNT heap_p; /* sides * |7|1|4| * |2| |3| * |5|0|6| */ int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1 }; int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2 }; double dx, dy, dist_to_nbr[8], ew_res, ns_res; double slope[8]; struct Cell_head window; int skip_diag; count = 0; first_cum = n_points; G_message(_("A* Search...")); Rast_get_window(&window); for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = nextdr[ct_dir]; c_nbr = nextdc[ct_dir]; /* account for rare cases when ns_res != ew_res */ dy = abs(r_nbr) * window.ns_res; dx = abs(c_nbr) * window.ew_res; if (ct_dir < 4) dist_to_nbr[ct_dir] = dx + dy; else dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy); } ew_res = window.ew_res; ns_res = window.ns_res; while (heap_size > 0) { G_percent(count++, n_points, 1); if (count > n_points) G_fatal_error(_("%lld surplus points"), heap_size); if (heap_size > n_points) G_fatal_error (_("Too many points in heap %lld, should be %lld"), heap_size, n_points); heap_p = heap_drop(); r = heap_p.pnt.r; c = heap_p.pnt.c; ele_val = heap_p.ele; for (ct_dir = 0; ct_dir < sides; ct_dir++) { /* get r, c (r_nbr, c_nbr) for neighbours */ r_nbr = r + nextdr[ct_dir]; c_nbr = c + nextdc[ct_dir]; slope[ct_dir] = ele_nbr[ct_dir] = 0; skip_diag = 0; /* check that neighbour is within region */ if (r_nbr < 0 || r_nbr >= nrows || c_nbr < 0 || c_nbr >= ncols) continue; seg_get(&aspflag, (char *)&af, r_nbr, c_nbr); is_in_list = FLAG_GET(af.flag, INLISTFLAG); is_worked = FLAG_GET(af.flag, WORKEDFLAG); if (!is_worked) { seg_get(&watalt, (char *)&wa, r_nbr, c_nbr); ele_nbr[ct_dir] = wa.ele; slope[ct_dir] = get_slope(ele_val, ele_nbr[ct_dir], dist_to_nbr[ct_dir]); } /* avoid diagonal flow direction bias */ if (!is_in_list) { if (ct_dir > 3 && slope[ct_dir] > 0) { if (slope[nbr_ew[ct_dir]] > 0) { /* slope to ew nbr > slope to center */ if (slope[ct_dir] < get_slope(ele_nbr[nbr_ew[ct_dir]], ele_nbr[ct_dir], ew_res)) skip_diag = 1; } if (!skip_diag && slope[nbr_ns[ct_dir]] > 0) { /* slope to ns nbr > slope to center */ if (slope[ct_dir] < get_slope(ele_nbr[nbr_ns[ct_dir]], ele_nbr[ct_dir], ns_res)) skip_diag = 1; } } } if (!skip_diag) { if (is_in_list == 0) { ele_up = ele_nbr[ct_dir]; af.asp = drain[r_nbr - r + 1][c_nbr - c + 1]; heap_add(r_nbr, c_nbr, ele_up); FLAG_SET(af.flag, INLISTFLAG); seg_put(&aspflag, (char *)&af, r_nbr, c_nbr); } else if (is_in_list && is_worked == 0) { if (FLAG_GET(af.flag, EDGEFLAG)) { /* neighbour is edge in list, not yet worked */ if (af.asp < 0) { /* adjust flow direction for edge cell */ af.asp = drain[r_nbr - r + 1][c_nbr - c + 1]; seg_put(&aspflag, (char *)&af, r_nbr, c_nbr); } } else if (FLAG_GET(af.flag, DEPRFLAG)) { G_debug(3, "real depression"); /* neighbour is inside real depression, not yet worked */ if (af.asp == 0 && ele_val <= ele_nbr[ct_dir]) { af.asp = drain[r_nbr - r + 1][c_nbr - c + 1]; FLAG_UNSET(af.flag, DEPRFLAG); seg_put(&aspflag, (char *)&af, r_nbr, c_nbr); } } } } } /* end neighbours */ /* add astar points to sorted list for flow accumulation and stream extraction */ first_cum--; seg_put(&astar_pts, (char *)&heap_p.pnt, 0, first_cum); seg_get(&aspflag, (char *)&af, r, c); FLAG_SET(af.flag, WORKEDFLAG); seg_put(&aspflag, (char *)&af, r, c); } /* end A* search */ G_percent(n_points, n_points, 1); /* finish it */ return 1; }
int main(int argc, char *argv[]) { int r, c; DCELL con1, con2; double d1, d2; DCELL *alt_row; const char *con_name, *alt_name; int file_fd; DCELL value; struct History history; struct GModule *module; struct Option *opt1, *opt2; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("surface")); G_add_keyword(_("interpolation")); module->description = _("Generates surface raster map from rasterized contours."); opt1 = G_define_standard_option(G_OPT_R_INPUT); opt1->description = _("Name of input raster map containing contours"); opt2 = G_define_standard_option(G_OPT_R_OUTPUT); if (G_parser(argc, argv)) exit(EXIT_FAILURE); con_name = opt1->answer; alt_name = opt2->answer; nrows = Rast_window_rows(); ncols = Rast_window_cols(); i_val_l_f = nrows + ncols; con = read_cell(con_name); alt_row = (DCELL *) G_malloc(ncols * sizeof(DCELL)); seen = flag_create(nrows, ncols); mask = flag_create(nrows, ncols); if (NULL != G_find_file("cell", "MASK", G_mapset())) { file_fd = Rast_open_old("MASK", G_mapset()); for (r = 0; r < nrows; r++) { Rast_get_d_row_nomask(file_fd, alt_row, r); for (c = 0; c < ncols; c++) if (Rast_is_d_null_value(&(alt_row[c])) || alt_row[c] == 0) FLAG_SET(mask, r, c); } Rast_close(file_fd); } zero = (NODE *) G_malloc(INIT_AR * sizeof(NODE)); minc = minr = 0; maxc = ncols - 1; maxr = nrows - 1; array_size = INIT_AR; file_fd = Rast_open_new(alt_name, DCELL_TYPE); for (r = 0; r < nrows; r++) { G_percent(r, nrows, 1); Rast_set_d_null_value(alt_row, ncols); for (c = 0; c < ncols; c++) { if (FLAG_GET(mask, r, c)) continue; value = con[r][c]; if (!Rast_is_d_null_value(&value)) { alt_row[c] = value; continue; } find_con(r, c, &d1, &d2, &con1, &con2); if (!Rast_is_d_null_value(&con2)) alt_row[c] = d2 * con1 / (d1 + d2) + d1 * con2 / (d1 + d2); else alt_row[c] = con1; } Rast_put_row(file_fd, alt_row, DCELL_TYPE); } G_percent(1, 1, 1); free_cell(con); flag_destroy(seen); flag_destroy(mask); Rast_close(file_fd); Rast_short_history(alt_name, "raster", &history); Rast_command_history(&history); Rast_write_history(alt_name, &history); exit(EXIT_SUCCESS); }
int close_maps(char *stream_rast, char *stream_vect, char *dir_rast) { int stream_fd, dir_fd, r, c, i; CELL *cell_buf1, *cell_buf2; struct History history; CELL stream_id; ASP_FLAG af; /* cheating... */ stream_fd = dir_fd = -1; cell_buf1 = cell_buf2 = NULL; G_message(_("Writing output raster maps...")); /* write requested output rasters */ if (stream_rast) { stream_fd = Rast_open_new(stream_rast, CELL_TYPE); cell_buf1 = Rast_allocate_c_buf(); } if (dir_rast) { dir_fd = Rast_open_new(dir_rast, CELL_TYPE); cell_buf2 = Rast_allocate_c_buf(); } for (r = 0; r < nrows; r++) { G_percent(r, nrows, 2); if (stream_rast) Rast_set_c_null_value(cell_buf1, ncols); /* reset row to all NULL */ if (dir_rast) Rast_set_c_null_value(cell_buf2, ncols); /* reset row to all NULL */ for (c = 0; c < ncols; c++) { if (stream_rast) { cseg_get(&stream, &stream_id, r, c); if (stream_id) cell_buf1[c] = stream_id; } if (dir_rast) { seg_get(&aspflag, (char *)&af, r, c); if (!FLAG_GET(af.flag, NULLFLAG)) { cell_buf2[c] = af.asp; } } } if (stream_rast) Rast_put_row(stream_fd, cell_buf1, CELL_TYPE); if (dir_rast) Rast_put_row(dir_fd, cell_buf2, CELL_TYPE); } G_percent(nrows, nrows, 2); /* finish it */ if (stream_rast) { Rast_close(stream_fd); G_free(cell_buf1); Rast_short_history(stream_rast, "raster", &history); Rast_command_history(&history); Rast_write_history(stream_rast, &history); } if (dir_rast) { struct Colors colors; Rast_close(dir_fd); G_free(cell_buf2); Rast_short_history(dir_rast, "raster", &history); Rast_command_history(&history); Rast_write_history(dir_rast, &history); Rast_init_colors(&colors); Rast_make_aspect_colors(&colors, -8, 8); Rast_write_colors(dir_rast, G_mapset(), &colors); } /* close stream vector */ if (stream_vect) { if (close_streamvect(stream_vect) < 0) G_fatal_error(_("Unable to write vector map <%s>"), stream_vect); } /* rearranging desk chairs on the Titanic... */ G_free(outlets); /* free stream nodes */ for (i = 1; i <= n_stream_nodes; i++) { if (stream_node[i].n_alloc > 0) { G_free(stream_node[i].trib); } } G_free(stream_node); return 1; }
int mean_shift(struct globals *globals) { int row, col, t; int n_changes; double alpha2; struct ngbr_stats Rin, Rout; double diff2; G_fatal_error(_("Mean shift is not yet implemented")); return FALSE; Rin.mean = G_malloc(globals->datasize); Rout.mean = G_malloc(globals->datasize); /* TODO: need another segment structure holding output * for mean shift, output of the previous iteration becomes input of the next iteration * initially, input and output are original band values */ alpha2 = globals->alpha * globals->alpha; t = 0; n_changes = 1; while (t < globals->end_t && n_changes > 0) { G_message(_("Processing pass %d..."), ++t); n_changes = 0; globals->candidate_count = 0; flag_clear_all(globals->candidate_flag); /* Set candidate flag to true/1 for all non-NULL cells */ for (row = globals->row_min; row < globals->row_max; row++) { for (col = globals->col_min; col < globals->col_max; col++) { if (!(FLAG_GET(globals->null_flag, row, col))) { FLAG_SET(globals->candidate_flag, row, col); globals->candidate_count++; } } } G_debug(4, "Starting to process %ld candidate cells", globals->candidate_count); /*process candidate cells */ G_percent_reset(); for (row = globals->row_min; row < globals->row_max; row++) { G_percent(row - globals->row_min, globals->row_max - globals->row_min, 4); for (col = globals->col_min; col < globals->col_max; col++) { if (!(FLAG_GET(globals->candidate_flag, row, col))) continue; /* get current band values */ Segment_get(&globals->bands_seg, (void *)Rin.mean, row, col); /* adapt initial spatial and range bandwiths */ /* calculate new band values */ /* if the squared difference between old and new band values * is larger than alpha2, then increase n_changes */ diff2 = (globals->calculate_similarity)(&Rin, &Rout, globals); if (diff2 > alpha2) n_changes++; } } } if (n_changes > 1) G_message(_("Mean shift stopped at %d due to reaching max iteration limit, more changes may be possible"), t); else G_message(_("Mean shift converged after %d iterations"), t); /* identify connected components */ return TRUE; }