123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- /****************************************************************************
- *
- * 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 "direction.h"
- #include "nodata.h"
- #include "common.h" /*for global opt->d8 flag*/
- #define TF_ROOTTWO 1.4142135623
- /* directions:
- 32 64 128
- 16 * 1
- 8 4 2
- */
- direction_type
- encodeDirection(const genericWindow<elevation_type>& elevwin,
- const dimension_type nrows, const dimension_type ncols,
- dimension_type row,
- dimension_type col) {
-
- /*check global opt flag and call appropriate model*/
- if(opt->d8){
- return encodeDirectionSFD(elevwin, nrows, ncols, row, col);
- }
- return encodeDirectionMFD(elevwin, nrows, ncols, row, col);
- }
- /***************************************************************/
- /* returns the direction corresponding to the window using MFD */
- direction_type
- encodeDirectionMFD(const genericWindow<elevation_type>& elevwin,
- const dimension_type nrows, const dimension_type ncols,
- dimension_type row,
- dimension_type col) {
-
- direction_type dir = DIRECTION_UNDEF;
-
- if(!is_nodata(elevwin.get())) {
- dir = 0;
- if (elevwin.get(5) < elevwin.get() && !is_void(elevwin.get(5))) dir |= 1;
- if (elevwin.get(3) < elevwin.get() && !is_void(elevwin.get(3))) dir |= 16;
- for(int i=0; i<3; i++) {
- if(elevwin.get(i) < elevwin.get() && !is_void(elevwin.get(i))) dir |= 32<<i;
- if(elevwin.get(i+6) < elevwin.get() && !is_void(elevwin.get(6+i))) dir |= 8>>i;
- }
- }
-
- /* if no direction, check for boundary */
- if(dir==0 || dir==DIRECTION_UNDEF) {
- if(row==0) {
- dir = 32 | 64 | 128;
- }
- if(row==nrows-1) {
- dir = 2 | 4 | 8;
- }
- if(col==0) {
- if(row==0) dir = 32;
- else if(row==nrows-1) dir = 8;
- else dir = 8 | 16 | 32;
- }
- if(col==ncols-1) {
- if(row==0) dir = 128;
- else if(row==nrows-1) dir = 2;
- else dir = 128 | 1 | 2;
- }
- }
- return dir;
- }
- /***************************************************************/
- /* returns the direction corresponding to the window using SFD */
- direction_type
- encodeDirectionSFD(const genericWindow<elevation_type>& elevwin,
- const dimension_type nrows, const dimension_type ncols,
- dimension_type row,
- dimension_type col) {
- direction_type dir = DIRECTION_UNDEF;
- float tdrop, max_drop;
- int max_indx;
-
- if(!is_nodata(elevwin.get())) {
- dir = 0;
- max_drop = 0;
- max_indx = -1;
- for(int i=0; i<9; i++){
- if(i%2==1){ /*cardinal direction*/
- tdrop=elevwin.get()-elevwin.get(i);
- if(tdrop>max_drop){ max_drop=tdrop; max_indx=i; }
- }
- else if(i!=4){ /*diagonal*/
- tdrop=(elevwin.get()-elevwin.get(i))/TF_ROOTTWO;
- if(tdrop>max_drop){ max_drop=tdrop; max_indx=i; }
- }
- }
- switch(max_indx){
- case 0:
- case 1:
- case 2:
- dir=32<<max_indx; break;
- case 3:
- dir=16; break;
- case 5:
- dir=1; break;
- case 6:
- case 7:
- case 8:
- dir=8>>(max_indx-6); break;
- default:
- dir=0; break;
- }
- }
-
- /* if no direction, check for boundary */
- if(dir==0 || dir==DIRECTION_UNDEF) {
- if(row==0) {
- dir = 64;
- }
- if(row==nrows-1) {
- dir = 48;
- }
- if(col==0) {
- if(row==0) dir = 32;
- else if(row==nrows-1) dir = 8;
- else dir = 16;
- }
- if(col==ncols-1) {
- if(row==0) dir = 128;
- else if(row==nrows-1) dir = 2;
- else dir = 1;
- }
- }
- return dir;
- }
- direction_type
- findDominant(direction_type dir) {
- switch(dir) {
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- case 32:
- case 64:
- case 128:
- return dir;
- case 1+2:
- case 128+1:
- return 1;
- case 2+4:
- case 4+8:
- return 4;
- case 8+16:
- case 16+32:
- return 16;
- case 32+64:
- case 64+128:
- return 64;
- case 1+2+4:
- return 2;
- case 2+4+8:
- return 4;
- case 4+8+16:
- return 8;
- case 8+16+32:
- return 16;
- case 16+32+64:
- return 32;
- case 32+64+128:
- return 64;
- case 64+128+1:
- return 128;
- case 128+1+2:
- return 1;
- case 128+1+2+4:
- case 64+128+1+2:
- return 1;
- case 1+2+4+8:
- case 2+4+8+16:
- return 4;
- case 8+16+32+64:
- case 4+8+16+32:
- return 16;
- case 32+64+128+1:
- case 16+32+64+128:
- return 64;
-
- case 64+128+1+2+4:
- return 1;
- case 128+1+2+4+8:
- return 2;
- case 1+2+4+8+16:
- return 4;
- case 2+4+8+16+32:
- return 8;
- case 4+8+16+32+64:
- return 16;
- case 8+16+32+64+128:
- return 32;
- case 16+32+64+128+1:
- return 64;
- case 32+64+128+1+2:
- return 128;
- }
- /* Otherwise, there is no dominant direction.
- * SFD must output a single direction 1,2,4,8,16,32,64, or 128
- * pick the first matching one, with preference to cardinal direction
- */
- if(dir & 85 ){
- /* at least one cardinal direction (1+4+16+64=E+S+W+N) matches */
- if(dir & 1){ return 1;}
- if(dir & 4){ return 4;}
- if(dir & 16){ return 16;}
- if(dir & 64){ return 64;}
- }
- else{
- /* 2 8 32 128 = SE SW NW NE*/
- if(dir & 2){ return 2;}
- if(dir & 8){ return 8;}
- if(dir & 32){ return 32;}
- if(dir & 128){ return 128;}
- }
- return dir; /* shouldn't get here unless dir <= 0 */
- }
- char
- directionSymbol(direction_type dir) {
- char c='?';
- int cnt=0;
- char symbols[] = ">\\v/<\\^/";
- if(dir == 0) return '.';
-
- dir = findDominant(dir);
- for(int i=0; i<8; i++) {
- if(dir & (1<<i)) {
- cnt++;
- c = symbols[i];
- }
- }
- if(cnt>1) c = 'X';
- switch(dir) {
- case 1+16:
- case 128+1+2+8+16+32:
- c = '-';
- break;
- case 1+2+8+16+32:
- case 128+1+8+16+32:
- c = '<';
- break;
- case 128+1+2+16+32:
- case 128+1+2+8+16:
- c = '>';
- break;
- case 4+64:
- case 2+4+8+32+64+128:
- c = '|';
- break;
- case 4+8+32+64+128:
- case 2+4+32+64+128:
- c = '^';
- break;
- case 2+4+8+64+128:
- case 2+4+8+32+64:
- c = 'v';
- break;
- case 255:
- c = '*';
- break;
- default:
- break;
- }
- return c;
- }
- #undef TF_ROOTTWO
|