123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- /****************************************************************************
- *
- * MODULE: r.terraflow
- *
- * COPYRIGHT (C) 2007 Laura Toma
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *****************************************************************************/
- #include <string.h>
- #include <assert.h>
- #include "grid.h"
- #include "common.h"
- #define GRID_DEBUG if(0)
- /* leave a border of 1 cell around */
- grid::grid(dimension_type giMin, dimension_type gjMin,
- dimension_type iMax, dimension_type jMax,
- long gsize, cclabel_type glabel) :
- iMin(giMin-1), jMin(gjMin-1), label(glabel), size(gsize) {
- width = jMax - jMin + 2;
- height = iMax - iMin + 2;
- assert((size_t)width*height*sizeof(gridElement) < getAvailableMemory());
- data = new gridElement[(size_t)width*height];
- assert(data);
- memset(data, 0, (size_t)width*height*sizeof(gridElement));
- }
- grid::~grid() {
- delete [] data;
- }
- void
- grid::load(AMI_STREAM<plateauType> &str) {
- AMI_err ae;
- plateauType *pt;
- GRID_DEBUG cout << "loading grid" << endl;
- for(int i=0; i<size; i++) {
- ae = str.read_item(&pt);
- assert(ae == AMI_ERROR_NO_ERROR);
- /* cout << *pt << endl; */
- assert(pt->valid);
- assert(pt->cclabel == label);
- dimension_type pti, ptj;
- pti = pt->i - iMin;
- ptj = pt->j - jMin;
- gridElement *datap = data + (size_t)pti * width + ptj;
- datap->dir = pt->dir;
- datap->depth = DEPTH_INITIAL; /* initial depth */
- datap->valid = 1;
- #ifdef KEEP_COORDS
- datap->i = pt->i;
- datap->j = pt->j;
- #endif
- if(datap->dir) {
- /* if it has a dir, it's on the boundary */
- boundaryQueue[0].enqueue(datap);
- }
- }
- }
- void
- grid::save(AMI_STREAM<waterType> &str) {
- GRID_DEBUG cout << "saving grid" << endl;
- for(dimension_type i=1; i<height-1; i++) {
- gridElement *rowp = data + (size_t)i * width;
- for(dimension_type j=1; j<width-1; j++) {
- gridElement *datap = rowp + j;
- if(datap->valid) {
- /* DONT save the label */
- waterType wt(i+iMin, j+jMin, datap->dir, LABEL_UNDEF, datap->depth);
- AMI_err ae = str.write_item(wt);
- assert(ae == AMI_ERROR_NO_ERROR);
- }
- }
- }
- }
- void
- grid::print() {
- cout << " ";
- for(int i=0; i<width; i++) {
- printf("%2d", (jMin + i%10));
- }
- cout << endl;
- for(int j=0; j<height; j++) {
- printf("%3d ", j + iMin);
- for(int i=0; i<width; i++) {
- if(data[i + (size_t)width * j].valid) {
- cout << " " << directionSymbol(data[i + (size_t)width * j].dir);
- } else {
- cout << " .";
- }
- }
- cout << endl;
- }
- }
- gridElement *
- grid::getNeighbour(gridElement *datap, int k) {
- switch(k) {
- case 0:
- datap += 1;
- break;
- case 1:
- datap += width + 1;
- break;
- case 2:
- datap += width;
- break;
- case 3:
- datap += width - 1;
- break;
- case 4:
- datap -= 1;
- break;
- case 5:
- datap -= (width + 1);
- break;
- case 6:
- datap -= width;
- break;
- case 7:
- datap -= (width - 1);
- break;
- default:
- assert(0);
- break;
- }
- return datap;
- }
- direction_type
- grid::getDirection(int k) {
- return 1<<((k+4)%8); /* converse direction */
- }
- void
- grid::assignDirections(int sfdmode) {
- gridElement *datap, *np;
-
- #ifdef KEEP_COORDS
- GRID_DEBUG cout << "points in queue=" << boundaryQueue[0].length() << endl;
- GRID_DEBUG for(int i=0; i<boundaryQueue[0].length(); i++) {
- boundaryQueue[0].peek(i,&datap);
- cout << datap->i << "," << datap->j << endl;
- }
- GRID_DEBUG cout << endl;
- #endif
-
- int k1=0, k2=1;
- while(!boundaryQueue[k1].isEmpty()) {
- while(boundaryQueue[k1].dequeue(&datap)) {
- /* should only find dominant if not on edge */
- if(sfdmode && datap->depth > DEPTH_INITIAL) {
- datap->dir = findDominant(datap->dir);
- }
- #ifdef KEEP_COORDS
- GRID_DEBUG cout << "(" << datap->i << "," << datap->j << ") "
- << "my direction is " << datap->dir;
- #endif
- for(int i=0; i<8; i++) {
- np = getNeighbour(datap, i);
- if(np->valid) {
- if(!np->dir) {
- np->depth = datap->depth + 1;
- boundaryQueue[k2].enqueue(np);
- #ifdef KEEP_COORDS
- GRID_DEBUG cout << " pushing " << "(" << np->i << "," << np->j << ")";
- #endif
- }
- if(np->depth == datap->depth + 1) { /* can only update ifin othr list */
- np->dir |= getDirection(i); /* neighbor points to us */
- /* if(!np->dir) np->dir |= getDirection(i); */
- }
- }
- }
- GRID_DEBUG cout << endl;
- }
- k1 ^= 1;
- k2 ^= 1;
- }
- }
|