123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- /****************************************************************************
- *
- * 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.
- *
- *****************************************************************************/
- #ifndef WATER_H
- #define WATER_H
- /* watershed analysis related structures */
- #include "types.h"
- #include "plateau.h"
- #include "nodata.h"
- #include "genericWindow.h"
- char directionSymbol(direction_type dir);
- class labelElevTypePrintLabel;
- /* ---------------------------------------------------------------------- */
- class labelElevType : public ijBaseType {
- friend class labelElevTypePrintLabel;
- protected:
- elevation_type el;
- cclabel_type label;
- public:
- labelElevType() : label(LABEL_UNDEF) {};
-
- labelElevType(dimension_type gi,
- dimension_type gj,
- elevation_type gel,
- cclabel_type glabel) :
- ijBaseType(gi, gj), el(gel), label(glabel) {};
-
- cclabel_type getLabel() const { return label; };
-
- elevation_type getElevation() const { return el; };
-
- friend ostream& operator << (ostream& s, const labelElevType &p);
- static char *printLabel(const labelElevType &p);
- friend class printLabel;
- };
- class ijCmpLabelElevType {
- public:
- static int compare(const labelElevType &a, const labelElevType &b) {
- return ijBaseType::compare(a, b);
- }
- };
- class labelCmpLabelElevType {
- public:
- static int compare(const labelElevType &a, const labelElevType &b) {
- return a.getLabel() - b.getLabel();
- /* return (a.getLabel() == b.getLabel() ? 0
- : (a.getLabel() < b.getLabel() ? -1 : 1)); */
- }
- };
- class labelElevTypePrintLabel {
- public:
- cclabel_type operator()(const labelElevType &p) {
- return p.label;
- }
- };
- /* ---------------------------------------------------------------------- */
- class waterCmpBoundaryType;
- class elevCmpBoundaryType;
- class boundaryCmpBoundaryType;
- class ijCmpBoundaryType;
- class boundaryType : public labelElevType {
- friend class waterCmpBoundaryType;
- friend class elevCmpBoundaryType;
- friend class boundaryCmpBoundaryType;
- protected:
- cclabel_type label2;
- public:
- boundaryType() : label2(LABEL_UNDEF) {};
-
- boundaryType(dimension_type gi,
- dimension_type gj,
- elevation_type gel,
- cclabel_type glabel1,
- cclabel_type glabel2) :
- labelElevType(gi, gj, gel, glabel1), label2(glabel2) {
- assert(glabel1 < glabel2);
- };
- boundaryType(labelElevType let, cclabel_type glabel2) : labelElevType(let) {
- if(let.getLabel() < glabel2) {
- label2 = glabel2;
- } else {
- label2 = label;
- label = glabel2;
- }
- };
- boundaryType(labelElevType let, elevation_type gel, cclabel_type glabel2)
- : labelElevType(let) {
- el = gel;
- if(let.getLabel() < glabel2) {
- label2 = glabel2;
- } else {
- label2 = label;
- label = glabel2;
- }
- };
- bool isValid() const { return label2 != LABEL_UNDEF; }
- cclabel_type getLabel1() const { return getLabel(); }
- cclabel_type getLabel2() const { return label2; }
- friend ostream& operator << (ostream& s, const boundaryType &p);
- static char *print(const boundaryType &p);
- };
- class ijCmpBoundaryType {
- public:
- static int compare(const boundaryType &a, const boundaryType &b) {
- return ijBaseType::compare(a, b);
- }
- }
- ;
- class waterCmpBoundaryType {
- public:
- static int compare(const boundaryType &a, const boundaryType &b) {
- if(a.label < b.label) return -1;
- if(a.label > b.label) return 1;
- if(a.label2 < b.label2) return -1;
- if(a.label2 > b.label2) return 1;
- if(a.el < b.el) return -1;
- if(a.el > b.el) return 1;
- return 0;
- }
- };
- class elevCmpBoundaryType {
- public:
- static int compare(const boundaryType &a, const boundaryType &b) {
- if(a.el < b.el) return -1;
- if(a.el > b.el) return 1;
- return 0;
- }
- };
- class boundaryCmpBoundaryType {
- public:
- static int compare(const boundaryType &a, const boundaryType &b) {
- if(a.label < b.label) return -1;
- if(a.label > b.label) return 1;
- if(a.label2 < b.label2) return -1;
- if(a.label2 > b.label2) return 1;
- return 0;
- }
- };
- /* ---------------------------------------------------------------------- */
- class fillPriority : public ijBaseType {
- protected:
- elevation_type el;
- bfs_depth_type depth;
- public:
- fillPriority() : ijBaseType(-1,-1), el(-1), depth(DEPTH_INITIAL) {};
- fillPriority(elevation_type gel,
- bfs_depth_type gdepth,
- dimension_type gi,
- dimension_type gj) :
- ijBaseType(gi, gj), el(gel), depth(gdepth) {}
- friend int operator<(const fillPriority &a, const fillPriority &b);
- friend int operator<=(const fillPriority &a, const fillPriority &b);
- friend int operator>(const fillPriority &a, const fillPriority &b);
- friend int operator==(const fillPriority &a, const fillPriority &b);
- friend int operator!=(const fillPriority &a, const fillPriority &b);
- friend ostream& operator << (ostream& s, const fillPriority &p);
- static int compare(const fillPriority &a, const fillPriority &b);
- static int qscompare(const void *a, const void *b);
- };
- /* ---------------------------------------------------------------------- */
- class fillPLabel : public fillPriority {
- cclabel_type label;
- public:
- fillPLabel() : label(LABEL_UNDEF) {};
- fillPLabel(const fillPriority &gpriority, const cclabel_type glabel) :
- fillPriority(gpriority), label(glabel) {}
- fillPriority getPriority() const { return (fillPriority)(*this); }
- cclabel_type getLabel() const { return label; }
- /* static char *print(const fillPLabel &p); */
- boundaryType getBoundary(cclabel_type label2) {
- if(label < label2) {
- return boundaryType(i, j, el, label, label2);
- } else {
- return boundaryType(i, j, el, label2, label);
- }
- }
- friend ostream& operator << (ostream& s, const fillPLabel &p) {
- return s << "[" << (fillPriority)p << ", " << p.label << "]";
- }
- };
- /* ---------------------------------------------------------------------- */
- class waterWindowBaseType {
- public:
- elevation_type el;
- direction_type dir;
- bfs_depth_type depth;
- waterWindowBaseType() : el(nodataType::ELEVATION_NODATA), dir(0),
- depth(DEPTH_INITIAL) {};
- waterWindowBaseType(elevation_type gel,
- direction_type gdir, bfs_depth_type gdepth) :
- el(gel), dir(gdir), depth(gdepth) {};
- friend int
- operator==(const waterWindowBaseType &a, const waterWindowBaseType &b) {
- return (a.el == b.el) && (a.dir == b.dir) && (a.depth == b.depth);
- }
-
- friend ostream& operator << (ostream& s, const waterWindowBaseType &p) {
- return s << "["
- << "el=" << p.el << ", "
- << "dir=" << p.dir << ", "
- << "depth=" << p.depth << "]";
- }
- };
- /* ---------------------------------------------------------------------- */
- class waterType;
- class waterGridType;
- class waterType : public ijBaseType {
- friend int ijCmp_waterType(const waterType &a, const waterType &b);
- friend class waterGridType;
- protected:
- direction_type dir;
- bfs_depth_type depth;
- cclabel_type label;
- public:
- waterType() : label(LABEL_UNDEF) {}; /* needed to sort */
- waterType(dimension_type gi,
- dimension_type gj,
- direction_type gdir,
- cclabel_type glabel=LABEL_UNDEF,
- bfs_depth_type gdepth=DEPTH_INITIAL) :
- ijBaseType(gi, gj), dir(gdir), depth(gdepth), label(glabel) {
- }
- waterType(plateauType &data) :
- ijBaseType(data.i, data.j),
- dir(data.dir), depth(DEPTH_INITIAL), label(data.cclabel) {
- };
- direction_type getDirection() const { return dir; }
- bfs_depth_type getDepth() const { return depth; }
- cclabel_type getLabel() const { return label; }
- static char *printLabel(const waterType &p);
- friend ostream& operator << (ostream& s, const waterType &p) {
- return s << "[waterType" << (ijBaseType)p
- << ", dir=" << p.dir
- << ", bfs=" << p.depth
- << ", lab=" << p.label << "]";
- }
- };
- class ijCmpWaterType {
- public:
- static int compare(const waterType &a, const waterType &b) {
- return ijBaseType::compare(a, b);
- }
- };
- #if(0)
- class waterType2direction_type {
- public:
- direction_type operator()(waterType p) { return p.getDirection(); }
- direction_type operator()(direction_type p) { return p; }
- };
- #endif
- /* ---------------------------------------------------------------------- */
- class waterGridType : public waterWindowBaseType {
- protected:
- cclabel_type label;
- public:
- waterGridType() : label(LABEL_UNDEF) {};
- waterGridType(elevation_type gel,
- direction_type gdir=DIRECTION_UNDEF,
- cclabel_type glabel=LABEL_UNDEF,
- bfs_depth_type gdepth=DEPTH_INITIAL) :
- waterWindowBaseType(gel, gdir, gdepth), label(glabel) {
- }
- waterGridType(elevation_type gel, waterType w) :
- waterWindowBaseType(gel, w.dir, w.depth), label(w.label) {}
-
- cclabel_type getLabel() const { return label; };
- void setLabel(cclabel_type lbl) { label=lbl; };
- friend ostream& operator << (ostream& s, const waterGridType &p) {
- return s << directionSymbol(p.dir);
- }
- };
- /* ---------------------------------------------------------------------- */
- class packed8bit {
- protected:
- unsigned char value;
- public:
- packed8bit() : value(0) {};
- void setBit(int k, int v=1) { value = (int) value | ((v?1:0)<<k); };
- void resetBit(int k) { value &= ~(0x1<<k); };
- int getBit(int k) const { return (value >> k) & 1; };
- };
- static int linear(int i, int j) {
- assert(i>=-1 && i<=1 && j>=-1 && j<=1);
- return ((i+1)*3+(j+1));
- }
- static int norm(int k) {
- return (k<4 ? k : (k>4?k-1:8));
- }
- static int norm(int i, int j) {
- return norm(linear(i,j));
- }
- class compressedWaterWindowBaseType : public ijBaseType {
- protected: /* 4 */
- bfs_depth_type depth; /* 4 */
- elevation_type el[9]; /* 18 */
- direction_type dir; /* 2 */
- /* we only need the depth if the elevation is the same. if so, the
- variation is bounded by +/-1. if a cell receives a label from a
- lower elevation (ie the center is lower than the cell), then the
- recipients depth must be 1 (it's on the edge). if the center is
- higher, then we have no interest in the cell. */
- unsigned short depth_delta; /* 2 */
- packed8bit points; /* 1 whether neighbor points to me */
- /* cells are numbered 0,1,2/3,4,5/6,7,8 */
- /* bits are 0,1,2,3,5,6,7,8 (skip 4) */
- public:
- compressedWaterWindowBaseType() : depth(DEPTH_INITIAL),
- dir(0) {
- for(int i=0; i<9; i++) { el[i] = nodataType::ELEVATION_NODATA; }
- };
- compressedWaterWindowBaseType(dimension_type gi,
- dimension_type gj,
- waterWindowBaseType *a,
- waterWindowBaseType *b,
- waterWindowBaseType *c);
- fillPriority getPriority() const;
- elevation_type getElevation(int k=4) const { return el[k]; };
- elevation_type getElevation(int i,int j) const{return el[linear(i,j)];};
- direction_type getDirection() const { return dir; };
- int drainsFrom(int i, int j) const {
- /* whether we drain water from cell i,j */
- return points.getBit(norm(i, j));
- };
- bfs_depth_type getDepth() const { return depth; };
- bfs_depth_type getDepth(int k) const;
- bfs_depth_type getDepth(int i, int j) const { return getDepth(norm(i,j)); };
- void sanityCheck();
-
- friend ostream& operator<<(ostream& s,
- const compressedWaterWindowBaseType &p);
- private:
- int computeDelta(waterWindowBaseType *center,
- int index, waterWindowBaseType *p) const;
- };
- class compressedWaterWindowType : public compressedWaterWindowBaseType {
- protected:
- cclabel_type label;
- public:
- compressedWaterWindowType() : compressedWaterWindowBaseType(),
- label(LABEL_UNDEF) {};
- compressedWaterWindowType(dimension_type gi,
- dimension_type gj,
- cclabel_type glabel,
- waterWindowBaseType *a,
- waterWindowBaseType *b,
- waterWindowBaseType *c)
- : compressedWaterWindowBaseType(gi, gj, a, b, c),
- label(glabel) {
- /* if nodata, labels are either depression labels, or undefined or
- boundary (a pseudo depression). */
- assert(!(is_nodata(getElevation())) ||
- (label==LABEL_BOUNDARY || label==LABEL_UNDEF));
- }
- cclabel_type getLabel() const { return label; };
- void setLabel(cclabel_type lbl) { label=lbl; };
- labelElevType getCenter() const;
-
- void sanityCheck();
-
- friend ostream& operator<<(ostream& s, const compressedWaterWindowType &p);
- };
- typedef compressedWaterWindowType waterWindowType;
- class ijCmpWaterWindowType {
- public:
- static int compare(const waterWindowType &a, const waterWindowType &b) {
- return ijBaseType::compare(a, b);
- }
- };
- class priorityCmpWaterWindowType {
- public:
- static int compare(const waterWindowType &a, const waterWindowType &b) {
- return fillPriority::compare(a.getPriority(), b.getPriority());
- }
- };
- /* ********************************************************************** */
- void
- createWaterWindows(AMI_STREAM<waterGridType> *mergedWaterStr,
- const dimension_type nrows, const dimension_type ncols,
- AMI_STREAM<waterWindowType> *waterWindows);
- /* ********************************************************************** */
- void
- generateWatersheds(AMI_STREAM<waterWindowType> **waterWindows,
- const dimension_type nrows, const dimension_type ncols,
- AMI_STREAM<labelElevType> *labeledWater,
- AMI_STREAM<boundaryType> *boundaryStr);
- void
- findBoundaries(AMI_STREAM<labelElevType> *labeledWater,
- const dimension_type nrows, const dimension_type ncols,
- AMI_STREAM<boundaryType> *boundaryStr);
- /* ********************************************************************** */
- #endif
|