sweep.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /****************************************************************************
  2. *
  3. * MODULE: r.terraflow
  4. *
  5. * COPYRIGHT (C) 2007 Laura Toma
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. *****************************************************************************/
  18. #ifndef _SWEEP_H
  19. #define _SWEEP_H
  20. #include <grass/iostream/ami.h>
  21. #include "option.h"
  22. #include "types.h"
  23. #include "weightWindow.h"
  24. class sweepOutput;
  25. class gridPosition;
  26. class flowStructure;
  27. class flowValue;
  28. class flowPriority;
  29. /* ---------------------------------------------------------------------- */
  30. class sweepOutput {
  31. public:
  32. dimension_type i,j; /* position in the grid */
  33. flowaccumulation_type accu; /* count */
  34. #ifdef OUTPUT_TCI
  35. tci_type tci; /* tci */
  36. #endif
  37. public:
  38. sweepOutput();
  39. /* computes output parameters given a flow value */
  40. void compute(elevation_type elev, dimension_type i, dimension_type j,
  41. const flowValue &flow, const weightWindow &wght,
  42. const elevation_type nodata);
  43. friend ostream& operator << (ostream& s, const sweepOutput &x) {
  44. return s << "[(" << x.i << ',' << x.j << "):"
  45. //<< form(" accu=%7.3f", x.accu)
  46. << " accu=" << x.accu
  47. #ifdef OUTPUT_TCI
  48. //<< form(", tci=%3.1f", x.tci)
  49. << ", tci=" << x.tci
  50. #endif
  51. << "]";
  52. }
  53. };
  54. /* ---------------------------------------------------------------------- */
  55. class ijCmpSweepOutput {
  56. public:
  57. static int compare(const sweepOutput &a, const sweepOutput &b) {
  58. if(a.i < b.i) return -1;
  59. if(a.i > b.i) return 1;
  60. if(a.j < b.j) return -1;
  61. if(a.j > b.j) return 1;
  62. return 0;
  63. }
  64. };
  65. /***************************************************************/
  66. class printAccumulation {
  67. public:
  68. flowaccumulation_type operator()(const sweepOutput &p) {
  69. return p.accu;
  70. }
  71. };
  72. /***************************************************************/
  73. class printAccumulationAscii {
  74. public:
  75. char *operator()(const sweepOutput &p) {
  76. static char buf[20];
  77. sprintf(buf, "%7.3f", p.accu);
  78. return buf;
  79. }
  80. };
  81. /***************************************************************/
  82. #ifdef OUTPUT_TCI
  83. class printTci {
  84. public:
  85. tci_type operator()(const sweepOutput &p) {
  86. return p.tci;
  87. }
  88. };
  89. class printTciAscii {
  90. public:
  91. char *operator()(const sweepOutput &p) {
  92. static char buf[20];
  93. sprintf(buf, "%7.3f", p.tci);
  94. return buf;
  95. }
  96. };
  97. #endif
  98. /***************************************************************/
  99. /***************************************************************/
  100. /* class 'grid_position' defines position in the grid */
  101. /***************************************************************/
  102. /***************************************************************/
  103. class gridPosition {
  104. public:
  105. dimension_type i,j;
  106. public:
  107. friend int operator == (const gridPosition &x,
  108. const gridPosition &y) {
  109. return ((x.i == y.i) && (x.j == y.j));
  110. }
  111. friend int operator != (const gridPosition &x,
  112. const gridPosition &y) {
  113. return (!(x == y));
  114. }
  115. friend int operator < (const gridPosition &x,
  116. const gridPosition &y) {
  117. return ((x.i < y.i) || ((x.i == y.i) && (x.j < y.j)));
  118. }
  119. friend int operator <= (const gridPosition &x,
  120. const gridPosition &y) {
  121. return ((x < y) || (x == y));
  122. }
  123. friend int operator > (const gridPosition &x,
  124. const gridPosition &y) {
  125. return ((x.i > y.i) || ((x.i == y.i) && (x.j > y.j)));
  126. }
  127. friend int operator >= (const gridPosition &x,
  128. const gridPosition &y) {
  129. return ((x > y) || (x == y));
  130. }
  131. };
  132. /*************************************************************/
  133. class flowPriority {
  134. public:
  135. elevation_type h;
  136. toporank_type toporank;
  137. /* points at same heights are processed in increasing order of their
  138. topological rank; overall, this gives topological order and
  139. guarantees that flow is never puhsed backwards. Note: of course,
  140. this is a way of waving hands on topological sorting. */
  141. dimension_type i,j;
  142. public:
  143. flowPriority(elevation_type a=0, toporank_type b=0,
  144. dimension_type c=0, dimension_type d=0):
  145. h(a), toporank(b), i(c), j(d) {}
  146. flowPriority(const flowPriority &p):
  147. h(p.h), toporank(p.toporank), i(p.i), j(p.j) {}
  148. ~flowPriority() {}
  149. elevation_type field1() const {
  150. return h;
  151. }
  152. dimension_type coord1() const {
  153. return i;
  154. }
  155. dimension_type coord2() const {
  156. return j;
  157. }
  158. void set (elevation_type g_h, toporank_type g_a,
  159. dimension_type g_i, dimension_type g_j) {
  160. h = g_h;
  161. toporank = g_a;
  162. i = g_i;
  163. j = g_j;
  164. }
  165. static int compare (const flowPriority &a, const flowPriority &b) {
  166. if (a.h > b.h) return -1;
  167. if (a.h < b.h) return 1;
  168. if (a.toporank < b.toporank) return -1;
  169. if (a.toporank > b.toporank) return 1;
  170. if (a.i < b.i) return -1;
  171. if (a.i > b.i) return 1;
  172. if (a.j < b.j) return -1;
  173. if (a.j > b.j) return 1;
  174. return 0;
  175. }
  176. friend int operator < (const flowPriority &p1,
  177. const flowPriority &p2) {
  178. if (p1.h > p2.h) return 1;
  179. if ((p1.h == p2.h) && (p1.toporank < p2.toporank)) return 1;
  180. if ((p1.h == p2.h) && (p1.toporank == p2.toporank)
  181. && (p1.i < p2.i)) return 1;
  182. if ((p1.h == p2.h) && (p1.toporank == p2.toporank)
  183. && (p1.i == p2.i) && (p1.j < p2.j)) return 1;
  184. return 0;
  185. }
  186. friend int operator <= (const flowPriority &p1,
  187. const flowPriority &p2) {
  188. return ((p1 < p2) || (p1 == p2));
  189. }
  190. friend int operator > (const flowPriority &p1,
  191. const flowPriority &p2) {
  192. /* return !(p1 < p2); */
  193. if (p1.h < p2.h) return 1;
  194. if ((p1.h == p2.h) && (p1.toporank > p2.toporank)) return 1;
  195. if ((p1.h == p2.h) && (p1.toporank == p2.toporank)
  196. && (p1.i > p2.i)) return 1;
  197. if ((p1.h == p2.h) && (p1.toporank == p2.toporank)
  198. && (p1.i == p2.i) && (p1.j > p2.j)) return 1;
  199. return 0;
  200. }
  201. friend int operator >= (const flowPriority &p1,
  202. const flowPriority &p2) {
  203. return ((p1 > p2) || (p1 == p2));
  204. }
  205. friend ostream& operator<<(ostream& s, const flowPriority &p) {
  206. return s << "(" << p.h << "," << p.toporank << ","
  207. << p.i << "," << p.j << ")";
  208. }
  209. friend istream& operator>>(istream& s, flowPriority &p) {
  210. return s >> p.h >> p.toporank >> p.i >> p.j;
  211. }
  212. friend bool operator==(const flowPriority &p1,
  213. const flowPriority &p2) {
  214. return ((p1.h == p2.h) && (p1.toporank == p2.toporank)
  215. && (p1.i == p2.i) && (p1.j == p2.j));
  216. }
  217. friend bool operator!=(const flowPriority &p1,
  218. const flowPriority &p2) {
  219. return (!(p1 == p2));
  220. }
  221. };
  222. /***************************************************************/
  223. /***************************************************************/
  224. /* class 'sweepItem' defines the structure of an element in the
  225. sweeping stream; it incorporates all info necessary during
  226. sweeping. */
  227. /***************************************************************/
  228. /***************************************************************/
  229. #define sweepItem sweepItemBaseType<toporank_type>
  230. template <class T>
  231. class sweepItemBaseType {
  232. public:
  233. dimension_type i,j;
  234. direction_type dir; /* precomputed direction */
  235. genericWindow<elevation_type> elevwin; /* elevation window */
  236. genericWindow<T> toporwin; /* topological_rank window */
  237. public:
  238. /***************************************************************/
  239. sweepItemBaseType(): i(0), j(0), dir(0), elevwin(), toporwin() {}
  240. /***************************************************************/
  241. sweepItemBaseType(const dimension_type &gi, const dimension_type &gj,
  242. const direction_type &gdir,
  243. elevation_type* a1,
  244. elevation_type* b1,
  245. elevation_type* c1,
  246. T* a2,
  247. T* b2,
  248. T* c2):
  249. i(gi), j(gj), dir(gdir), elevwin(a1,b1,c1), toporwin(a2,b2,c2) {}
  250. /***************************************************************/
  251. ~sweepItemBaseType() {}
  252. /***************************************************************/
  253. /* return the elevation window */
  254. genericWindow<elevation_type> getElevWindow() const {
  255. return elevwin;
  256. }
  257. /***************************************************************/
  258. /* return the elevation window */
  259. genericWindow<T> getTopoRankWindow() const {
  260. return toporwin;
  261. }
  262. /***************************************************************/
  263. /* return coordinates */
  264. dimension_type getI() const {
  265. return i;
  266. }
  267. /***************************************************************/
  268. dimension_type getJ() const {
  269. return j;
  270. }
  271. /***************************************************************/
  272. /* return the elevation of the item */
  273. elevation_type getElev() const {
  274. return elevwin.get();
  275. }
  276. /***************************************************************/
  277. /* return elevation of one of neighbours: di,dj in {-1,0,1} */
  278. elevation_type getElev(short di, short dj) const {
  279. return elevwin.get(di,dj);
  280. }
  281. /***************************************************************/
  282. /* return elevation of one of neighbours: index in {0..8} */
  283. elevation_type getElev(unsigned short index) const {
  284. return elevwin.get(index);
  285. }
  286. /***************************************************************/
  287. direction_type getDir() const {
  288. return dir;
  289. }
  290. /***************************************************************/
  291. /* return the toporank (arcinfo accumulation) of the item */
  292. T getTopoRank() const {
  293. return toporwin.get();
  294. }
  295. /***************************************************************/
  296. /* return the topoRank (arcinfo accumulation) of one of neighbours:
  297. di,dj in {-1,0,1} */
  298. T getTopoRank(short di, short dj) const {
  299. return toporwin.get(di,dj);
  300. }
  301. /***************************************************************/
  302. /* return the topoRank (arcinfo accumulation) of one of neighbours:
  303. index in {0..8} */
  304. T getTopoRank(unsigned short index) const {
  305. return toporwin.get(index);
  306. }
  307. /***************************************************************/
  308. flowPriority getPriority() const {
  309. return flowPriority(elevwin.get(), toporwin.get(), i,j);
  310. }
  311. /***************************************************************/
  312. /* define the operators which will be used to sort the sweeping
  313. stream the sweep elements should be ordered in increasing orders of
  314. flowPriority */
  315. friend int operator < (const sweepItemBaseType<T> &x,
  316. const sweepItemBaseType<T> &y) {
  317. if (x.getPriority() < y.getPriority()) return 1;
  318. return (0);
  319. }
  320. /***************************************************************/
  321. friend int operator > (const sweepItemBaseType<T> &x,
  322. const sweepItemBaseType<T> &y) {
  323. if (x.getPriority() > y.getPriority()) return 1;
  324. return (0);
  325. }
  326. /***************************************************************/
  327. friend ostream& operator<<(ostream& s, const sweepItemBaseType<T> &x) {
  328. return s << x.getPriority() << ", "
  329. << x.getDir() <<"\n"
  330. << "elev:\n" << x.getElevWindow()
  331. << "topo rank:\n" << x.getTopoRankWindow();
  332. }
  333. };
  334. class PrioCmpSweepItem {
  335. public:
  336. static int compare(const sweepItem &a, const sweepItem &b) {
  337. return flowPriority::compare(a.getPriority(), b.getPriority());
  338. }
  339. };
  340. /************************************************************/
  341. class flowValue {
  342. public:
  343. flowaccumulation_type value;
  344. public:
  345. flowValue(flowaccumulation_type x=0): value(x) {}
  346. ~flowValue() {}
  347. flowaccumulation_type get() const {
  348. return value;
  349. }
  350. friend ostream& operator<<(ostream& s, const flowValue &elt) {
  351. return s << elt.value;
  352. }
  353. friend istream& operator>>(istream& s, flowValue &elt) {
  354. return s >> elt.value;
  355. }
  356. friend flowValue operator +(const flowValue &elt1,
  357. const flowValue &elt2) {
  358. flowValue elt(elt1.value + elt2.value);
  359. return elt;
  360. }
  361. flowValue operator =(const flowValue &elt) {
  362. value = elt.value;
  363. return *this;
  364. }
  365. flowValue operator != (const flowValue &elt) {
  366. return value != elt.value;
  367. }
  368. flowValue operator == (const flowValue &elt) {
  369. return value == elt.value;
  370. }
  371. friend int operator > (const flowValue &p1, const flowValue &p2) {
  372. return (p1.value > p2.value);
  373. }
  374. friend int operator >= (const flowValue &p1,
  375. const flowValue &p2) {
  376. return (p1.value >= p2.value);
  377. }
  378. friend int operator < (const flowValue &p1,
  379. const flowValue &p2) {
  380. return (p1.value < p2.value);
  381. }
  382. friend int operator <= (const flowValue &p1,
  383. const flowValue &p2) {
  384. return (p1.value <= p2.value);
  385. }
  386. };
  387. /************************************************************/
  388. class flowStructure {
  389. private:
  390. flowPriority prio;
  391. flowValue val;
  392. public:
  393. flowStructure(const flowPriority &p = 0, const flowValue &e = 0):
  394. prio(p), val(e) {}
  395. /* flowStructure(const flowValue &e, const flowPriority &p):
  396. prio(p), val(e) {}
  397. */
  398. flowStructure(const flowStructure &fl) {
  399. prio = fl.prio;
  400. val = fl.val;
  401. }
  402. ~flowStructure() {}
  403. flowPriority getPriority() const {
  404. return prio;
  405. }
  406. flowValue getValue() const {
  407. return val;
  408. }
  409. friend ostream& operator<<(ostream& s, const flowStructure &fl) {
  410. return s << "[<prio=" << fl.prio << "> " << fl.val <<"]";
  411. }
  412. friend int operator < (const flowStructure &f1,
  413. const flowStructure &f2) {
  414. return (f1.prio < f2.prio);
  415. }
  416. friend int operator <= (const flowStructure &f1,
  417. const flowStructure &f2) {
  418. return (f1.prio <= f2.prio);
  419. }
  420. friend int operator > (const flowStructure &f1,
  421. const flowStructure &f2) {
  422. return (f1.prio > f2.prio);
  423. }
  424. friend int operator >= (const flowStructure &f1,
  425. const flowStructure &f2) {
  426. return (f1.prio >= f2.prio);
  427. }
  428. friend bool operator == (const flowStructure &f1,
  429. const flowStructure &f2) {
  430. return (f1.prio == f2.prio);
  431. }
  432. friend bool operator != (const flowStructure &f1,
  433. const flowStructure &f2) {
  434. return (f1.prio != f2.prio);
  435. }
  436. friend flowStructure operator +(const flowStructure &x,
  437. const flowStructure &y) {
  438. flowValue val = x.val + y.val;
  439. flowStructure f(x.prio, val);
  440. return f;
  441. }
  442. static int qscompare(const void *a, const void *b) {
  443. flowStructure* x, *y;
  444. x = (flowStructure*) a;
  445. y = (flowStructure*) b;
  446. if (*x < *y) return -1;
  447. if (*x == *y) return 0;
  448. return 1;
  449. }
  450. };
  451. /***************************************************************/
  452. /* Read the points in order from the sweep stream and process them.
  453. If trustdir = 1 then trust and use the directions contained in the
  454. sweep stream. Otherwise push flow to all downslope neighbors and
  455. use the direction only for points without downslope neighbors. */
  456. /***************************************************************/
  457. AMI_STREAM<sweepOutput>* sweep(AMI_STREAM<sweepItem> *sweepstr,
  458. flowaccumulation_type D8CUT,
  459. const int trustdir);
  460. #endif