main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. /****************************************************************************
  2. *
  3. * MODULE: r.li.patchnum
  4. * AUTHOR(S): Claudio Porta and Lucio Davide Spano (original contributors)
  5. * students of Computer Science University of Pisa (Italy)
  6. * Commission from Faunalia Pontedera (PI) www.faunalia.it
  7. * Fixes: Markus Neteler <neteler itc.it>
  8. * Rewrite: Markus Metz
  9. * Patch identification: Michael Shapiro - CERL
  10. *
  11. * PURPOSE: calculates patch number index
  12. * COPYRIGHT: (C) 2007-2014 by the GRASS Development Team
  13. *
  14. * This program is free software under the GNU General Public
  15. * License (>=v2). Read the file COPYING that comes with GRASS
  16. * for details.
  17. *
  18. *****************************************************************************/
  19. #include <stdlib.h>
  20. #include <fcntl.h>
  21. #include <grass/gis.h>
  22. #include <grass/raster.h>
  23. #include <grass/glocale.h>
  24. #include "../r.li.daemon/daemon.h"
  25. #include "../r.li.daemon/GenericCell.h"
  26. /* template for patch density, mps, padcv, padrange, padsd */
  27. /* cell count and type of each patch */
  28. struct pst {
  29. long count;
  30. generic_cell type;
  31. };
  32. int calculate(int fd, struct area_entry *ad, double *result);
  33. int calculateD(int fd, struct area_entry *ad, double *result);
  34. int calculateF(int fd, struct area_entry *ad, double *result);
  35. int main(int argc, char *argv[])
  36. {
  37. struct Option *raster, *conf, *output;
  38. struct GModule *module;
  39. G_gisinit(argv[0]);
  40. module = G_define_module();
  41. module->description =
  42. _("Calculates patch number index on a raster map, using a 4 neighbour algorithm.");
  43. G_add_keyword(_("raster"));
  44. G_add_keyword(_("landscape structure analysis"));
  45. G_add_keyword(_("patch index"));
  46. /* define options */
  47. raster = G_define_standard_option(G_OPT_R_INPUT);
  48. conf = G_define_standard_option(G_OPT_F_INPUT);
  49. conf->key = "config";
  50. conf->description = _("Configuration file");
  51. conf->required = YES;
  52. output = G_define_standard_option(G_OPT_R_OUTPUT);
  53. if (G_parser(argc, argv))
  54. exit(EXIT_FAILURE);
  55. return calculateIndex(conf->answer, patch_number, NULL, raster->answer,
  56. output->answer);
  57. }
  58. int patch_number(int fd, char **par, struct area_entry *ad, double *result)
  59. {
  60. int ris = RLI_OK;
  61. double indice = 0;
  62. switch (ad->data_type) {
  63. case CELL_TYPE:
  64. {
  65. calculate(fd, ad, &indice);
  66. break;
  67. }
  68. case DCELL_TYPE:
  69. {
  70. calculateD(fd, ad, &indice);
  71. break;
  72. }
  73. case FCELL_TYPE:
  74. {
  75. calculateF(fd, ad, &indice);
  76. break;
  77. }
  78. default:
  79. {
  80. G_fatal_error("data type unknown");
  81. return RLI_ERRORE;
  82. }
  83. }
  84. if (ris != RLI_OK) {
  85. return RLI_ERRORE;
  86. }
  87. *result = indice;
  88. return RLI_OK;
  89. }
  90. int calculate(int fd, struct area_entry *ad, double *result)
  91. {
  92. CELL *buf, *buf_sup, *buf_null;
  93. CELL corrCell, precCell, supCell;
  94. long npatch, area;
  95. long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
  96. struct pst *pst;
  97. long nalloc, incr;
  98. int i, j, k;
  99. int connected;
  100. int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
  101. struct Cell_head hd;
  102. Rast_get_window(&hd);
  103. buf_null = Rast_allocate_c_buf();
  104. Rast_set_c_null_value(buf_null, Rast_window_cols());
  105. buf_sup = buf_null;
  106. /* initialize patch ids */
  107. pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
  108. pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
  109. for (j = 0; j < Rast_window_cols(); j++) {
  110. pid_corr[j] = 0;
  111. pid_sup[j] = 0;
  112. }
  113. /* open mask if needed */
  114. mask_fd = -1;
  115. mask_buf = mask_sup = NULL;
  116. masked = FALSE;
  117. if (ad->mask == 1) {
  118. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  119. return RLI_ERRORE;
  120. mask_buf = G_malloc(ad->cl * sizeof(int));
  121. if (mask_buf == NULL) {
  122. G_fatal_error("malloc mask_buf failed");
  123. return RLI_ERRORE;
  124. }
  125. mask_sup = G_malloc(ad->cl * sizeof(int));
  126. if (mask_sup == NULL) {
  127. G_fatal_error("malloc mask_buf failed");
  128. return RLI_ERRORE;
  129. }
  130. for (j = 0; j < ad->cl; j++)
  131. mask_buf[j] = 0;
  132. masked = TRUE;
  133. }
  134. /* calculate number of patches */
  135. npatch = 0;
  136. area = 0;
  137. pid = 0;
  138. /* patch size and type */
  139. incr = 1024;
  140. if (incr > ad->rl)
  141. incr = ad->rl;
  142. if (incr > ad->cl)
  143. incr = ad->cl;
  144. if (incr < 2)
  145. incr = 2;
  146. nalloc = incr;
  147. pst = G_malloc(nalloc * sizeof(struct pst));
  148. for (k = 0; k < nalloc; k++) {
  149. pst[k].count = 0;
  150. }
  151. for (i = 0; i < ad->rl; i++) {
  152. buf = RLI_get_cell_raster_row(fd, i + ad->y, ad);
  153. if (i > 0) {
  154. buf_sup = RLI_get_cell_raster_row(fd, i - 1 + ad->y, ad);
  155. }
  156. if (masked) {
  157. mask_tmp = mask_sup;
  158. mask_sup = mask_buf;
  159. mask_buf = mask_tmp;
  160. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  161. return 0;
  162. }
  163. ltmp = pid_sup;
  164. pid_sup = pid_corr;
  165. pid_corr = ltmp;
  166. Rast_set_c_null_value(&precCell, 1);
  167. connected = 0;
  168. for (j = 0; j < ad->cl; j++) {
  169. pid_corr[j + ad->x] = 0;
  170. corrCell = buf[j + ad->x];
  171. if (masked && (mask_buf[j] == 0)) {
  172. Rast_set_c_null_value(&corrCell, 1);
  173. }
  174. if (Rast_is_c_null_value(&corrCell)) {
  175. connected = 0;
  176. precCell = corrCell;
  177. continue;
  178. }
  179. area++;
  180. supCell = buf_sup[j + ad->x];
  181. if (masked && (mask_sup[j] == 0)) {
  182. Rast_set_c_null_value(&supCell, 1);
  183. }
  184. if (!Rast_is_c_null_value(&precCell) && corrCell == precCell) {
  185. pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
  186. connected = 1;
  187. pst[pid_corr[j + ad->x]].count++;
  188. }
  189. else {
  190. connected = 0;
  191. }
  192. if (!Rast_is_c_null_value(&supCell) && corrCell == supCell) {
  193. if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
  194. /* connect or merge */
  195. /* after r.clump */
  196. if (connected) {
  197. npatch--;
  198. if (npatch == 0) {
  199. G_fatal_error("npatch == 0 at row %d, col %d", i, j);
  200. }
  201. }
  202. old_pid = pid_corr[j + ad->x];
  203. new_pid = pid_sup[j + ad->x];
  204. pid_corr[j + ad->x] = new_pid;
  205. if (old_pid > 0) {
  206. /* merge */
  207. /* update left side of the current row */
  208. for (k = 0; k < j; k++) {
  209. if (pid_corr[k + ad->x] == old_pid)
  210. pid_corr[k + ad->x] = new_pid;
  211. }
  212. /* update right side of the previous row */
  213. for (k = j + 1; k < ad->cl; k++) {
  214. if (pid_sup[k + ad->x] == old_pid)
  215. pid_sup[k + ad->x] = new_pid;
  216. }
  217. pst[new_pid].count += pst[old_pid].count;
  218. pst[old_pid].count = 0;
  219. if (old_pid == pid)
  220. pid--;
  221. }
  222. else {
  223. pst[new_pid].count++;
  224. }
  225. }
  226. connected = 1;
  227. }
  228. if (!connected) {
  229. /* start new patch */
  230. npatch++;
  231. pid++;
  232. pid_corr[j + ad->x] = pid;
  233. if (pid >= nalloc) {
  234. pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
  235. for (k = nalloc; k < pid + incr; k++)
  236. pst[k].count = 0;
  237. nalloc = pid + incr;
  238. }
  239. pst[pid].count = 1;
  240. pst[pid].type.t = CELL_TYPE;
  241. pst[pid].type.val.c = corrCell;
  242. }
  243. precCell = corrCell;
  244. }
  245. }
  246. *result = npatch;
  247. if (masked) {
  248. close(mask_fd);
  249. G_free(mask_buf);
  250. G_free(mask_sup);
  251. }
  252. G_free(buf_null);
  253. G_free(pid_corr);
  254. G_free(pid_sup);
  255. G_free(pst);
  256. return RLI_OK;
  257. }
  258. int calculateD(int fd, struct area_entry *ad, double *result)
  259. {
  260. DCELL *buf, *buf_sup, *buf_null;
  261. DCELL corrCell, precCell, supCell;
  262. long npatch, area;
  263. long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
  264. struct pst *pst;
  265. long nalloc, incr;
  266. int i, j, k;
  267. int connected;
  268. int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
  269. struct Cell_head hd;
  270. Rast_get_window(&hd);
  271. buf_null = Rast_allocate_d_buf();
  272. Rast_set_d_null_value(buf_null, Rast_window_cols());
  273. buf_sup = buf_null;
  274. /* initialize patch ids */
  275. pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
  276. pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
  277. for (j = 0; j < Rast_window_cols(); j++) {
  278. pid_corr[j] = 0;
  279. pid_sup[j] = 0;
  280. }
  281. /* open mask if needed */
  282. mask_fd = -1;
  283. mask_buf = mask_sup = NULL;
  284. masked = FALSE;
  285. if (ad->mask == 1) {
  286. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  287. return RLI_ERRORE;
  288. mask_buf = G_malloc(ad->cl * sizeof(int));
  289. if (mask_buf == NULL) {
  290. G_fatal_error("malloc mask_buf failed");
  291. return RLI_ERRORE;
  292. }
  293. mask_sup = G_malloc(ad->cl * sizeof(int));
  294. if (mask_sup == NULL) {
  295. G_fatal_error("malloc mask_buf failed");
  296. return RLI_ERRORE;
  297. }
  298. for (j = 0; j < ad->cl; j++)
  299. mask_buf[j] = 0;
  300. masked = TRUE;
  301. }
  302. /* calculate number of patches */
  303. npatch = 0;
  304. area = 0;
  305. pid = 0;
  306. /* patch size and type */
  307. incr = 1024;
  308. if (incr > ad->rl)
  309. incr = ad->rl;
  310. if (incr > ad->cl)
  311. incr = ad->cl;
  312. if (incr < 2)
  313. incr = 2;
  314. nalloc = incr;
  315. pst = G_malloc(nalloc * sizeof(struct pst));
  316. for (k = 0; k < nalloc; k++) {
  317. pst[k].count = 0;
  318. }
  319. for (i = 0; i < ad->rl; i++) {
  320. buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
  321. if (i > 0) {
  322. buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
  323. }
  324. if (masked) {
  325. mask_tmp = mask_sup;
  326. mask_sup = mask_buf;
  327. mask_buf = mask_tmp;
  328. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  329. return 0;
  330. }
  331. ltmp = pid_sup;
  332. pid_sup = pid_corr;
  333. pid_corr = ltmp;
  334. Rast_set_d_null_value(&precCell, 1);
  335. connected = 0;
  336. for (j = 0; j < ad->cl; j++) {
  337. pid_corr[j + ad->x] = 0;
  338. corrCell = buf[j + ad->x];
  339. if (masked && (mask_buf[j] == 0)) {
  340. Rast_set_d_null_value(&corrCell, 1);
  341. }
  342. if (Rast_is_d_null_value(&corrCell)) {
  343. connected = 0;
  344. precCell = corrCell;
  345. continue;
  346. }
  347. area++;
  348. supCell = buf_sup[j + ad->x];
  349. if (masked && (mask_sup[j] == 0)) {
  350. Rast_set_d_null_value(&supCell, 1);
  351. }
  352. if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
  353. pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
  354. connected = 1;
  355. pst[pid_corr[j + ad->x]].count++;
  356. }
  357. else {
  358. connected = 0;
  359. }
  360. if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
  361. if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
  362. /* connect or merge */
  363. /* after r.clump */
  364. if (connected) {
  365. npatch--;
  366. if (npatch == 0) {
  367. G_fatal_error("npatch == 0 at row %d, col %d", i, j);
  368. }
  369. }
  370. old_pid = pid_corr[j + ad->x];
  371. new_pid = pid_sup[j + ad->x];
  372. pid_corr[j + ad->x] = new_pid;
  373. if (old_pid > 0) {
  374. /* merge */
  375. /* update left side of the current row */
  376. for (k = 0; k < j; k++) {
  377. if (pid_corr[k + ad->x] == old_pid)
  378. pid_corr[k + ad->x] = new_pid;
  379. }
  380. /* update right side of the previous row */
  381. for (k = j + 1; k < ad->cl; k++) {
  382. if (pid_sup[k + ad->x] == old_pid)
  383. pid_sup[k + ad->x] = new_pid;
  384. }
  385. pst[new_pid].count += pst[old_pid].count;
  386. pst[old_pid].count = 0;
  387. if (old_pid == pid)
  388. pid--;
  389. }
  390. else {
  391. pst[new_pid].count++;
  392. }
  393. }
  394. connected = 1;
  395. }
  396. if (!connected) {
  397. /* start new patch */
  398. npatch++;
  399. pid++;
  400. pid_corr[j + ad->x] = pid;
  401. if (pid >= nalloc) {
  402. pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
  403. for (k = nalloc; k < pid + incr; k++)
  404. pst[k].count = 0;
  405. nalloc = pid + incr;
  406. }
  407. pst[pid].count = 1;
  408. pst[pid].type.t = CELL_TYPE;
  409. pst[pid].type.val.c = corrCell;
  410. }
  411. precCell = corrCell;
  412. }
  413. }
  414. *result = npatch;
  415. if (masked) {
  416. close(mask_fd);
  417. G_free(mask_buf);
  418. G_free(mask_sup);
  419. }
  420. G_free(buf_null);
  421. G_free(pid_corr);
  422. G_free(pid_sup);
  423. G_free(pst);
  424. return RLI_OK;
  425. }
  426. int calculateF(int fd, struct area_entry *ad, double *result)
  427. {
  428. FCELL *buf, *buf_sup, *buf_null;
  429. FCELL corrCell, precCell, supCell;
  430. long npatch, area;
  431. long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
  432. struct pst *pst;
  433. long nalloc, incr;
  434. int i, j, k;
  435. int connected;
  436. int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
  437. struct Cell_head hd;
  438. Rast_get_window(&hd);
  439. buf_null = Rast_allocate_f_buf();
  440. Rast_set_f_null_value(buf_null, Rast_window_cols());
  441. buf_sup = buf_null;
  442. /* initialize patch ids */
  443. pid_corr = G_malloc(Rast_window_cols() * sizeof(long));
  444. pid_sup = G_malloc(Rast_window_cols() * sizeof(long));
  445. for (j = 0; j < Rast_window_cols(); j++) {
  446. pid_corr[j] = 0;
  447. pid_sup[j] = 0;
  448. }
  449. /* open mask if needed */
  450. mask_fd = -1;
  451. mask_buf = mask_sup = NULL;
  452. masked = FALSE;
  453. if (ad->mask == 1) {
  454. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  455. return RLI_ERRORE;
  456. mask_buf = G_malloc(ad->cl * sizeof(int));
  457. if (mask_buf == NULL) {
  458. G_fatal_error("malloc mask_buf failed");
  459. return RLI_ERRORE;
  460. }
  461. mask_sup = G_malloc(ad->cl * sizeof(int));
  462. if (mask_sup == NULL) {
  463. G_fatal_error("malloc mask_buf failed");
  464. return RLI_ERRORE;
  465. }
  466. for (j = 0; j < ad->cl; j++)
  467. mask_buf[j] = 0;
  468. masked = TRUE;
  469. }
  470. /* calculate number of patches */
  471. npatch = 0;
  472. area = 0;
  473. pid = 0;
  474. /* patch size and type */
  475. incr = 1024;
  476. if (incr > ad->rl)
  477. incr = ad->rl;
  478. if (incr > ad->cl)
  479. incr = ad->cl;
  480. if (incr < 2)
  481. incr = 2;
  482. nalloc = incr;
  483. pst = G_malloc(nalloc * sizeof(struct pst));
  484. for (k = 0; k < nalloc; k++) {
  485. pst[k].count = 0;
  486. }
  487. for (i = 0; i < ad->rl; i++) {
  488. buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
  489. if (i > 0) {
  490. buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
  491. }
  492. if (masked) {
  493. mask_tmp = mask_sup;
  494. mask_sup = mask_buf;
  495. mask_buf = mask_tmp;
  496. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  497. return 0;
  498. }
  499. ltmp = pid_sup;
  500. pid_sup = pid_corr;
  501. pid_corr = ltmp;
  502. Rast_set_f_null_value(&precCell, 1);
  503. connected = 0;
  504. for (j = 0; j < ad->cl; j++) {
  505. pid_corr[j + ad->x] = 0;
  506. corrCell = buf[j + ad->x];
  507. if (masked && (mask_buf[j] == 0)) {
  508. Rast_set_f_null_value(&corrCell, 1);
  509. }
  510. if (Rast_is_f_null_value(&corrCell)) {
  511. connected = 0;
  512. precCell = corrCell;
  513. continue;
  514. }
  515. area++;
  516. supCell = buf_sup[j + ad->x];
  517. if (masked && (mask_sup[j] == 0)) {
  518. Rast_set_f_null_value(&supCell, 1);
  519. }
  520. if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
  521. pid_corr[j + ad->x] = pid_corr[j - 1 + ad->x];
  522. connected = 1;
  523. pst[pid_corr[j + ad->x]].count++;
  524. }
  525. else {
  526. connected = 0;
  527. }
  528. if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
  529. if (pid_corr[j + ad->x] != pid_sup[j + ad->x]) {
  530. /* connect or merge */
  531. /* after r.clump */
  532. if (connected) {
  533. npatch--;
  534. if (npatch == 0) {
  535. G_fatal_error("npatch == 0 at row %d, col %d", i, j);
  536. }
  537. }
  538. old_pid = pid_corr[j + ad->x];
  539. new_pid = pid_sup[j + ad->x];
  540. pid_corr[j + ad->x] = new_pid;
  541. if (old_pid > 0) {
  542. /* merge */
  543. /* update left side of the current row */
  544. for (k = 0; k < j; k++) {
  545. if (pid_corr[k + ad->x] == old_pid)
  546. pid_corr[k + ad->x] = new_pid;
  547. }
  548. /* update right side of the previous row */
  549. for (k = j + 1; k < ad->cl; k++) {
  550. if (pid_sup[k + ad->x] == old_pid)
  551. pid_sup[k + ad->x] = new_pid;
  552. }
  553. pst[new_pid].count += pst[old_pid].count;
  554. pst[old_pid].count = 0;
  555. if (old_pid == pid)
  556. pid--;
  557. }
  558. else {
  559. pst[new_pid].count++;
  560. }
  561. }
  562. connected = 1;
  563. }
  564. if (!connected) {
  565. /* start new patch */
  566. npatch++;
  567. pid++;
  568. pid_corr[j + ad->x] = pid;
  569. if (pid >= nalloc) {
  570. pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
  571. for (k = nalloc; k < pid + incr; k++)
  572. pst[k].count = 0;
  573. nalloc = pid + incr;
  574. }
  575. pst[pid].count = 1;
  576. pst[pid].type.t = CELL_TYPE;
  577. pst[pid].type.val.c = corrCell;
  578. }
  579. precCell = corrCell;
  580. }
  581. }
  582. *result = npatch;
  583. if (masked) {
  584. close(mask_fd);
  585. G_free(mask_buf);
  586. G_free(mask_sup);
  587. }
  588. G_free(buf_null);
  589. G_free(pid_corr);
  590. G_free(pid_sup);
  591. G_free(pst);
  592. return RLI_OK;
  593. }