main.c 15 KB

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