mps.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /****************************************************************************
  2. *
  3. * MODULE: r.li.patchnum
  4. * AUTHOR(S): Serena Pallecchi (original contributor)
  5. * student of Computer Science University of Pisa (Italy)
  6. * Commission from Faunalia Pontedera (PI) www.faunalia.it
  7. * Rewrite: Markus Metz
  8. * Patch identification: Michael Shapiro - CERL
  9. *
  10. * PURPOSE: calculates mean patch size index
  11. * COPYRIGHT: (C) 2007-2014 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <stdlib.h>
  19. #include <fcntl.h>
  20. #include <math.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 is patchnum */
  27. /* cell count and type of each patch */
  28. struct pst {
  29. long count;
  30. generic_cell type;
  31. };
  32. rli_func meanPatchSize;
  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 mean patch size 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, meanPatchSize, NULL, raster->answer,
  57. output->answer);
  58. }
  59. int meanPatchSize(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. if (npatch > 0) {
  248. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  249. double area_units;
  250. /* calculate distance */
  251. G_begin_distance_calculations();
  252. /* EW Dist at North edge */
  253. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  254. /* EW Dist at South Edge */
  255. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  256. /* NS Dist at East edge */
  257. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  258. /* NS Dist at West edge */
  259. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  260. area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  261. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
  262. *result = area_units / (npatch * 10000);
  263. }
  264. else {
  265. *result = 0;
  266. }
  267. if (masked) {
  268. close(mask_fd);
  269. G_free(mask_buf);
  270. G_free(mask_sup);
  271. }
  272. G_free(buf_null);
  273. G_free(pid_corr);
  274. G_free(pid_sup);
  275. G_free(pst);
  276. return RLI_OK;
  277. }
  278. int calculateD(int fd, struct area_entry *ad, double *result)
  279. {
  280. DCELL *buf, *buf_sup, *buf_null;
  281. DCELL corrCell, precCell, supCell;
  282. long npatch, area;
  283. long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
  284. struct pst *pst;
  285. long nalloc, incr;
  286. int i, j, k;
  287. int connected;
  288. int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
  289. struct Cell_head hd;
  290. Rast_get_window(&hd);
  291. buf_null = Rast_allocate_d_buf();
  292. Rast_set_d_null_value(buf_null, Rast_window_cols());
  293. buf_sup = buf_null;
  294. /* initialize patch ids */
  295. pid_corr = G_malloc(ad->cl * sizeof(long));
  296. pid_sup = G_malloc(ad->cl * sizeof(long));
  297. for (j = 0; j < ad->cl; j++) {
  298. pid_corr[j] = 0;
  299. pid_sup[j] = 0;
  300. }
  301. /* open mask if needed */
  302. mask_fd = -1;
  303. mask_buf = mask_sup = NULL;
  304. masked = FALSE;
  305. if (ad->mask == 1) {
  306. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  307. return RLI_ERRORE;
  308. mask_buf = G_malloc(ad->cl * sizeof(int));
  309. if (mask_buf == NULL) {
  310. G_fatal_error("malloc mask_buf failed");
  311. return RLI_ERRORE;
  312. }
  313. mask_sup = G_malloc(ad->cl * sizeof(int));
  314. if (mask_sup == NULL) {
  315. G_fatal_error("malloc mask_buf failed");
  316. return RLI_ERRORE;
  317. }
  318. for (j = 0; j < ad->cl; j++)
  319. mask_buf[j] = 0;
  320. masked = TRUE;
  321. }
  322. /* calculate number of patches */
  323. npatch = 0;
  324. area = 0;
  325. pid = 0;
  326. /* patch size and type */
  327. incr = 1024;
  328. if (incr > ad->rl)
  329. incr = ad->rl;
  330. if (incr > ad->cl)
  331. incr = ad->cl;
  332. if (incr < 2)
  333. incr = 2;
  334. nalloc = incr;
  335. pst = G_malloc(nalloc * sizeof(struct pst));
  336. for (k = 0; k < nalloc; k++) {
  337. pst[k].count = 0;
  338. }
  339. for (i = 0; i < ad->rl; i++) {
  340. buf = RLI_get_dcell_raster_row(fd, i + ad->y, ad);
  341. if (i > 0) {
  342. buf_sup = RLI_get_dcell_raster_row(fd, i - 1 + ad->y, ad);
  343. }
  344. if (masked) {
  345. mask_tmp = mask_sup;
  346. mask_sup = mask_buf;
  347. mask_buf = mask_tmp;
  348. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  349. return 0;
  350. }
  351. ltmp = pid_sup;
  352. pid_sup = pid_corr;
  353. pid_corr = ltmp;
  354. Rast_set_d_null_value(&precCell, 1);
  355. connected = 0;
  356. for (j = 0; j < ad->cl; j++) {
  357. pid_corr[j] = 0;
  358. corrCell = buf[j + ad->x];
  359. if (masked && (mask_buf[j] == 0)) {
  360. Rast_set_d_null_value(&corrCell, 1);
  361. }
  362. if (Rast_is_d_null_value(&corrCell)) {
  363. connected = 0;
  364. precCell = corrCell;
  365. continue;
  366. }
  367. area++;
  368. supCell = buf_sup[j + ad->x];
  369. if (masked && (mask_sup[j] == 0)) {
  370. Rast_set_d_null_value(&supCell, 1);
  371. }
  372. if (!Rast_is_d_null_value(&precCell) && corrCell == precCell) {
  373. pid_corr[j] = pid_corr[j - 1];
  374. connected = 1;
  375. pst[pid_corr[j]].count++;
  376. }
  377. else {
  378. connected = 0;
  379. }
  380. if (!Rast_is_d_null_value(&supCell) && corrCell == supCell) {
  381. if (pid_corr[j] != pid_sup[j]) {
  382. /* connect or merge */
  383. /* after r.clump */
  384. if (connected) {
  385. npatch--;
  386. if (npatch == 0) {
  387. G_fatal_error("npatch == 0 at row %d, col %d", i, j);
  388. }
  389. }
  390. old_pid = pid_corr[j];
  391. new_pid = pid_sup[j];
  392. pid_corr[j] = new_pid;
  393. if (old_pid > 0) {
  394. /* merge */
  395. /* update left side of the current row */
  396. for (k = 0; k < j; k++) {
  397. if (pid_corr[k] == old_pid)
  398. pid_corr[k] = new_pid;
  399. }
  400. /* update right side of the previous row */
  401. for (k = j + 1; k < ad->cl; k++) {
  402. if (pid_sup[k] == old_pid)
  403. pid_sup[k] = new_pid;
  404. }
  405. pst[new_pid].count += pst[old_pid].count;
  406. pst[old_pid].count = 0;
  407. if (old_pid == pid)
  408. pid--;
  409. }
  410. else {
  411. pst[new_pid].count++;
  412. }
  413. }
  414. connected = 1;
  415. }
  416. if (!connected) {
  417. /* start new patch */
  418. npatch++;
  419. pid++;
  420. pid_corr[j] = pid;
  421. if (pid >= nalloc) {
  422. pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
  423. for (k = nalloc; k < pid + incr; k++)
  424. pst[k].count = 0;
  425. nalloc = pid + incr;
  426. }
  427. pst[pid].count = 1;
  428. pst[pid].type.t = CELL_TYPE;
  429. pst[pid].type.val.c = corrCell;
  430. }
  431. precCell = corrCell;
  432. }
  433. }
  434. if (npatch > 0) {
  435. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  436. double area_units;
  437. /* calculate distance */
  438. G_begin_distance_calculations();
  439. /* EW Dist at North edge */
  440. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  441. /* EW Dist at South Edge */
  442. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  443. /* NS Dist at East edge */
  444. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  445. /* NS Dist at West edge */
  446. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  447. area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  448. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
  449. *result = area_units / (npatch * 10000);
  450. }
  451. else {
  452. *result = 0;
  453. }
  454. if (masked) {
  455. close(mask_fd);
  456. G_free(mask_buf);
  457. G_free(mask_sup);
  458. }
  459. G_free(buf_null);
  460. G_free(pid_corr);
  461. G_free(pid_sup);
  462. G_free(pst);
  463. return RLI_OK;
  464. }
  465. int calculateF(int fd, struct area_entry *ad, double *result)
  466. {
  467. FCELL *buf, *buf_sup, *buf_null;
  468. FCELL corrCell, precCell, supCell;
  469. long npatch, area;
  470. long pid, old_pid, new_pid, *pid_corr, *pid_sup, *ltmp;
  471. struct pst *pst;
  472. long nalloc, incr;
  473. int i, j, k;
  474. int connected;
  475. int mask_fd, *mask_buf, *mask_sup, *mask_tmp, masked;
  476. struct Cell_head hd;
  477. Rast_get_window(&hd);
  478. buf_null = Rast_allocate_f_buf();
  479. Rast_set_f_null_value(buf_null, Rast_window_cols());
  480. buf_sup = buf_null;
  481. /* initialize patch ids */
  482. pid_corr = G_malloc(ad->cl * sizeof(long));
  483. pid_sup = G_malloc(ad->cl * sizeof(long));
  484. for (j = 0; j < ad->cl; j++) {
  485. pid_corr[j] = 0;
  486. pid_sup[j] = 0;
  487. }
  488. /* open mask if needed */
  489. mask_fd = -1;
  490. mask_buf = mask_sup = NULL;
  491. masked = FALSE;
  492. if (ad->mask == 1) {
  493. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  494. return RLI_ERRORE;
  495. mask_buf = G_malloc(ad->cl * sizeof(int));
  496. if (mask_buf == NULL) {
  497. G_fatal_error("malloc mask_buf failed");
  498. return RLI_ERRORE;
  499. }
  500. mask_sup = G_malloc(ad->cl * sizeof(int));
  501. if (mask_sup == NULL) {
  502. G_fatal_error("malloc mask_buf failed");
  503. return RLI_ERRORE;
  504. }
  505. for (j = 0; j < ad->cl; j++)
  506. mask_buf[j] = 0;
  507. masked = TRUE;
  508. }
  509. /* calculate number of patches */
  510. npatch = 0;
  511. area = 0;
  512. pid = 0;
  513. /* patch size and type */
  514. incr = 1024;
  515. if (incr > ad->rl)
  516. incr = ad->rl;
  517. if (incr > ad->cl)
  518. incr = ad->cl;
  519. if (incr < 2)
  520. incr = 2;
  521. nalloc = incr;
  522. pst = G_malloc(nalloc * sizeof(struct pst));
  523. for (k = 0; k < nalloc; k++) {
  524. pst[k].count = 0;
  525. }
  526. for (i = 0; i < ad->rl; i++) {
  527. buf = RLI_get_fcell_raster_row(fd, i + ad->y, ad);
  528. if (i > 0) {
  529. buf_sup = RLI_get_fcell_raster_row(fd, i - 1 + ad->y, ad);
  530. }
  531. if (masked) {
  532. mask_tmp = mask_sup;
  533. mask_sup = mask_buf;
  534. mask_buf = mask_tmp;
  535. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0)
  536. return 0;
  537. }
  538. ltmp = pid_sup;
  539. pid_sup = pid_corr;
  540. pid_corr = ltmp;
  541. Rast_set_f_null_value(&precCell, 1);
  542. connected = 0;
  543. for (j = 0; j < ad->cl; j++) {
  544. pid_corr[j] = 0;
  545. corrCell = buf[j + ad->x];
  546. if (masked && (mask_buf[j] == 0)) {
  547. Rast_set_f_null_value(&corrCell, 1);
  548. }
  549. if (Rast_is_f_null_value(&corrCell)) {
  550. connected = 0;
  551. precCell = corrCell;
  552. continue;
  553. }
  554. area++;
  555. supCell = buf_sup[j + ad->x];
  556. if (masked && (mask_sup[j] == 0)) {
  557. Rast_set_f_null_value(&supCell, 1);
  558. }
  559. if (!Rast_is_f_null_value(&precCell) && corrCell == precCell) {
  560. pid_corr[j] = pid_corr[j - 1];
  561. connected = 1;
  562. pst[pid_corr[j]].count++;
  563. }
  564. else {
  565. connected = 0;
  566. }
  567. if (!Rast_is_f_null_value(&supCell) && corrCell == supCell) {
  568. if (pid_corr[j] != pid_sup[j]) {
  569. /* connect or merge */
  570. /* after r.clump */
  571. if (connected) {
  572. npatch--;
  573. if (npatch == 0) {
  574. G_fatal_error("npatch == 0 at row %d, col %d", i, j);
  575. }
  576. }
  577. old_pid = pid_corr[j];
  578. new_pid = pid_sup[j];
  579. pid_corr[j] = new_pid;
  580. if (old_pid > 0) {
  581. /* merge */
  582. /* update left side of the current row */
  583. for (k = 0; k < j; k++) {
  584. if (pid_corr[k] == old_pid)
  585. pid_corr[k] = new_pid;
  586. }
  587. /* update right side of the previous row */
  588. for (k = j + 1; k < ad->cl; k++) {
  589. if (pid_sup[k] == old_pid)
  590. pid_sup[k] = new_pid;
  591. }
  592. pst[new_pid].count += pst[old_pid].count;
  593. pst[old_pid].count = 0;
  594. if (old_pid == pid)
  595. pid--;
  596. }
  597. else {
  598. pst[new_pid].count++;
  599. }
  600. }
  601. connected = 1;
  602. }
  603. if (!connected) {
  604. /* start new patch */
  605. npatch++;
  606. pid++;
  607. pid_corr[j] = pid;
  608. if (pid >= nalloc) {
  609. pst = (struct pst *)G_realloc(pst, (pid + incr) * sizeof(struct pst));
  610. for (k = nalloc; k < pid + incr; k++)
  611. pst[k].count = 0;
  612. nalloc = pid + incr;
  613. }
  614. pst[pid].count = 1;
  615. pst[pid].type.t = CELL_TYPE;
  616. pst[pid].type.val.c = corrCell;
  617. }
  618. precCell = corrCell;
  619. }
  620. }
  621. if (npatch > 0) {
  622. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  623. double area_units;
  624. /* calculate distance */
  625. G_begin_distance_calculations();
  626. /* EW Dist at North edge */
  627. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  628. /* EW Dist at South Edge */
  629. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  630. /* NS Dist at East edge */
  631. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  632. /* NS Dist at West edge */
  633. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  634. area_units = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  635. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * area;
  636. *result = area_units / (npatch * 10000);
  637. }
  638. else {
  639. *result = 0;
  640. }
  641. if (masked) {
  642. close(mask_fd);
  643. G_free(mask_buf);
  644. G_free(mask_sup);
  645. }
  646. G_free(buf_null);
  647. G_free(pid_corr);
  648. G_free(pid_sup);
  649. G_free(pst);
  650. return RLI_OK;
  651. }