mps.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. /*
  2. * \brief calculates mean patch size index
  3. *
  4. * \AUTHOR: Serena Pallecchi student of Computer Science University of Pisa (Italy)
  5. * Commission from Faunalia Pontedera (PI) www.faunalia.it
  6. *
  7. * This program is free software under the GPL (>=v2)
  8. * Read the COPYING file that comes with GRASS for details.
  9. *
  10. */
  11. #include <stdlib.h>
  12. #include <fcntl.h>
  13. #include <math.h>
  14. #include <grass/gis.h>
  15. #include <grass/raster.h>
  16. #include <grass/glocale.h>
  17. #include "../r.li.daemon/defs.h"
  18. #include "../r.li.daemon/avlDefs.h"
  19. #include "../r.li.daemon/avlID.h"
  20. #include "../r.li.daemon/daemon.h"
  21. int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
  22. int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
  23. int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result);
  24. int main(int argc, char *argv[])
  25. {
  26. struct Option *raster, *conf, *output;
  27. struct GModule *module;
  28. G_gisinit(argv[0]);
  29. module = G_define_module();
  30. module->description =
  31. _("Calculates mean patch size index on a raster map, using a 4 neighbour algorithm");
  32. G_add_keyword(_("raster"));
  33. G_add_keyword(_("landscape structure analysis"));
  34. G_add_keyword(_("patch index"));
  35. /* define options */
  36. raster = G_define_standard_option(G_OPT_R_INPUT);
  37. conf = G_define_standard_option(G_OPT_F_INPUT);
  38. conf->key = "config";
  39. conf->description = _("Configuration file");
  40. conf->required = YES;
  41. output = G_define_standard_option(G_OPT_R_OUTPUT);
  42. if (G_parser(argc, argv))
  43. exit(EXIT_FAILURE);
  44. return calculateIndex(conf->answer, meanPatchSize, NULL, raster->answer,
  45. output->answer);
  46. }
  47. int meanPatchSize(int fd, char **par, struct area_entry *ad, double *result)
  48. {
  49. int ris = 0;
  50. double indice = 0;
  51. struct Cell_head hd;
  52. Rast_get_cellhd(ad->raster, "", &hd);
  53. switch (ad->data_type) {
  54. case CELL_TYPE:
  55. {
  56. ris = calculate(fd, ad, hd, &indice);
  57. break;
  58. }
  59. case DCELL_TYPE:
  60. {
  61. ris = calculateD(fd, ad, hd, &indice);
  62. break;
  63. }
  64. case FCELL_TYPE:
  65. {
  66. ris = calculateF(fd, ad, hd, &indice);
  67. break;
  68. }
  69. default:
  70. {
  71. G_fatal_error("data type unknown");
  72. return RLI_ERRORE;
  73. }
  74. }
  75. if (ris != RLI_OK) {
  76. return RLI_ERRORE;
  77. }
  78. *result = indice;
  79. return RLI_OK;
  80. }
  81. int calculate(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
  82. {
  83. CELL *buf;
  84. CELL *buf_sup;
  85. CELL corrCell;
  86. CELL precCell;
  87. CELL supCell;
  88. int i, j;
  89. int mask_fd = -1, *mask_buf;
  90. int ris = 0;
  91. int masked = FALSE;
  92. long npatch = 0;
  93. long tot = 0;
  94. long zero = 0;
  95. long uno = 1;
  96. long idCorr = 0;
  97. long lastId = 0;
  98. long doppi = 0;
  99. long *mask_patch_sup;
  100. long *mask_patch_corr;
  101. double indice = 0;
  102. double area = 0; /*if all cells are null area=0 */
  103. double areaCorrect = 0;
  104. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  105. avlID_tree albero = NULL;
  106. avlID_table *array;
  107. /* open mask if needed */
  108. if (ad->mask == 1) {
  109. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  110. return RLI_ERRORE;
  111. mask_buf = G_malloc(ad->cl * sizeof(int));
  112. if (mask_buf == NULL) {
  113. G_fatal_error("malloc mask_buf failed");
  114. return RLI_ERRORE;
  115. }
  116. masked = TRUE;
  117. }
  118. mask_patch_sup = G_malloc(ad->cl * sizeof(long));
  119. if (mask_patch_sup == NULL) {
  120. G_fatal_error("malloc mask_patch_sup failed");
  121. return RLI_ERRORE;
  122. }
  123. mask_patch_corr = G_malloc(ad->cl * sizeof(long));
  124. if (mask_patch_corr == NULL) {
  125. G_fatal_error("malloc mask_patch_corr failed");
  126. return RLI_ERRORE;
  127. }
  128. buf_sup = Rast_allocate_c_buf();
  129. if (buf_sup == NULL) {
  130. G_fatal_error("malloc buf_sup failed");
  131. return RLI_ERRORE;
  132. }
  133. buf = Rast_allocate_c_buf();
  134. if (buf == NULL) {
  135. G_fatal_error("malloc buf failed");
  136. return RLI_ERRORE;
  137. }
  138. Rast_set_c_null_value(buf_sup + ad->x, ad->cl); /*the first time buf_sup is all null */
  139. for (i = 0; i < ad->cl; i++) {
  140. mask_patch_sup[i] = 0;
  141. mask_patch_corr[i] = 0;
  142. }
  143. /*for each raster row */
  144. for (j = 0; j < ad->rl; j++) {
  145. if (j > 0) {
  146. buf_sup = RLI_get_cell_raster_row(fd, j - 1 + ad->y, ad);
  147. }
  148. buf = RLI_get_cell_raster_row(fd, j + ad->y, ad);
  149. if (masked) {
  150. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  151. G_fatal_error("mask read failed");
  152. return RLI_ERRORE;
  153. }
  154. }
  155. Rast_set_c_null_value(&precCell, 1);
  156. for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
  157. corrCell = buf[i + ad->x];
  158. if ((masked) && (mask_buf[i + ad->x] == 0)) {
  159. Rast_set_c_null_value(&corrCell, 1);
  160. }
  161. /*valid cell */
  162. if (!(Rast_is_null_value(&corrCell, CELL_TYPE))) {
  163. area++;
  164. if (i > 0)
  165. precCell = buf[i - 1 + ad->x];
  166. if (j == 0)
  167. Rast_set_c_null_value(&supCell, 1);
  168. else
  169. supCell = buf_sup[i + ad->x];
  170. if (corrCell != precCell) {
  171. if (corrCell != supCell) {
  172. /*new patch */
  173. if (idCorr == 0) { /*first patch */
  174. lastId = 1;
  175. idCorr = 1;
  176. mask_patch_corr[i] = idCorr;
  177. }
  178. else { /*not first patch */
  179. /* put in the tree previous values */
  180. if (albero == NULL) {
  181. albero = avlID_make(idCorr, uno);
  182. if (albero == NULL) {
  183. G_fatal_error("avlID_make error");
  184. return RLI_ERRORE;
  185. }
  186. npatch++;
  187. }
  188. else { /* tree not null */
  189. ris = avlID_add(&albero, idCorr, uno);
  190. switch (ris) {
  191. case AVL_ERR:
  192. {
  193. G_fatal_error("avlID_add error");
  194. return RLI_ERRORE;
  195. }
  196. case AVL_ADD:
  197. {
  198. npatch++;
  199. break;
  200. }
  201. case AVL_PRES:
  202. {
  203. break;
  204. }
  205. default:
  206. {
  207. G_fatal_error
  208. ("avlID_add unknown error");
  209. return RLI_ERRORE;
  210. }
  211. }
  212. }
  213. lastId++;
  214. idCorr = lastId;
  215. mask_patch_corr[i] = idCorr;
  216. }
  217. }
  218. else { /*current cell and upper cell are equal */
  219. if ((corrCell == precCell) &&
  220. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  221. long r = 0;
  222. long del = mask_patch_sup[i];
  223. r = avlID_sub(&albero, del);
  224. if (r == 0) {
  225. G_fatal_error("avlID_sub error");
  226. return RLI_ERRORE;
  227. }
  228. /*Remove one patch because it makes part of a patch already found */
  229. ris = avlID_add(&albero, idCorr, uno);
  230. switch (ris) {
  231. case AVL_ERR:
  232. {
  233. G_fatal_error("avlID_add error");
  234. return RLI_ERRORE;
  235. }
  236. case AVL_ADD:
  237. {
  238. npatch++;
  239. break;
  240. }
  241. case AVL_PRES:
  242. {
  243. break;
  244. }
  245. default:
  246. {
  247. G_fatal_error("avlID_add unknown error");
  248. return RLI_ERRORE;
  249. }
  250. }
  251. r = i;
  252. while (i < ad->cl) {
  253. if (mask_patch_sup[r] == del) {
  254. mask_patch_sup[r] = idCorr;
  255. }
  256. else {
  257. r = ad->cl + 1;
  258. }
  259. }
  260. }
  261. if (albero == NULL) {
  262. albero = avlID_make(idCorr, uno);
  263. if (albero == NULL) {
  264. G_fatal_error("avlID_make error");
  265. return RLI_ERRORE;
  266. }
  267. npatch++;
  268. }
  269. else { /* tree not null */
  270. ris = avlID_add(&albero, idCorr, uno);
  271. switch (ris) {
  272. case AVL_ERR:
  273. {
  274. G_fatal_error("avlID_add error");
  275. return RLI_ERRORE;
  276. }
  277. case AVL_ADD:
  278. {
  279. npatch++;
  280. break;
  281. }
  282. case AVL_PRES:
  283. {
  284. break;
  285. }
  286. default:
  287. {
  288. G_fatal_error("avlID_add unknown error");
  289. return RLI_ERRORE;
  290. }
  291. }
  292. }
  293. idCorr = mask_patch_sup[i];
  294. mask_patch_corr[i] = idCorr;
  295. }
  296. }
  297. else { /*current cell and previous cell are equal */
  298. if ((corrCell == supCell) &&
  299. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  300. int l;
  301. mask_patch_corr[i] = mask_patch_sup[i];
  302. l = i - 1;
  303. while (l >= 0) {
  304. if (mask_patch_corr[l] == idCorr) {
  305. mask_patch_corr[l] = mask_patch_sup[i];
  306. l--;
  307. }
  308. else {
  309. l = (-1);
  310. }
  311. }
  312. lastId--;
  313. idCorr = mask_patch_sup[i];
  314. }
  315. else {
  316. mask_patch_corr[i] = idCorr;
  317. }
  318. }
  319. }
  320. else { /*cell not to consider or cell is null */
  321. mask_patch_corr[i] = 0;
  322. }
  323. }
  324. mask_patch_sup = mask_patch_corr;
  325. }
  326. if (area != 0) {
  327. if (albero == NULL) {
  328. albero = avlID_make(idCorr, uno);
  329. if (albero == NULL) {
  330. G_fatal_error("avlID_make error");
  331. return RLI_ERRORE;
  332. }
  333. npatch++;
  334. }
  335. else {
  336. ris = avlID_add(&albero, idCorr, uno);
  337. switch (ris) {
  338. case AVL_ERR:
  339. {
  340. G_fatal_error("avlID_add error");
  341. return RLI_ERRORE;
  342. }
  343. case AVL_ADD:
  344. {
  345. npatch++;
  346. break;
  347. }
  348. case AVL_PRES:
  349. {
  350. break;
  351. }
  352. default:
  353. {
  354. G_fatal_error("avlID_add unknown error");
  355. return RLI_ERRORE;
  356. }
  357. }
  358. }
  359. array = G_malloc(npatch * sizeof(avlID_tableRow));
  360. if (array == NULL) {
  361. G_fatal_error("malloc array failed");
  362. return RLI_ERRORE;
  363. }
  364. tot = avlID_to_array(albero, zero, array);
  365. if (tot != npatch) {
  366. G_warning
  367. ("avlID_to_array unaspected value. the result could be wrong");
  368. return RLI_ERRORE;
  369. }
  370. for (i = 0; i < npatch; i++) {
  371. if (array[i]->tot == 0)
  372. doppi++;
  373. }
  374. npatch = npatch - doppi;
  375. /*calculate distance */
  376. G_begin_distance_calculations();
  377. /* EW Dist at North edge */
  378. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  379. /* EW Dist at South Edge */
  380. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  381. /* NS Dist at East edge */
  382. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  383. /* NS Dist at West edge */
  384. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  385. areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  386. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
  387. indice = areaCorrect / npatch;
  388. G_free(array);
  389. }
  390. else
  391. indice = (double)(0);
  392. *result = indice;
  393. if (masked)
  394. G_free(mask_buf);
  395. G_free(mask_patch_corr);
  396. G_free(buf_sup);
  397. return RLI_OK;
  398. }
  399. int calculateD(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
  400. {
  401. DCELL *buf;
  402. DCELL *buf_sup;
  403. DCELL corrCell;
  404. DCELL precCell;
  405. DCELL supCell;
  406. int i, j;
  407. int mask_fd = -1, *mask_buf;
  408. int ris = 0;
  409. int masked = FALSE;
  410. long npatch = 0;
  411. long tot = 0;
  412. long zero = 0;
  413. long uno = 1;
  414. long idCorr = 0;
  415. long lastId = 0;
  416. long doppi = 0;
  417. long *mask_patch_sup;
  418. long *mask_patch_corr;
  419. double indice = 0;
  420. double area = 0; /*if all cells are null area=0 */
  421. double areaCorrect = 0;
  422. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  423. avlID_tree albero = NULL;
  424. avlID_table *array;
  425. /* open mask if needed */
  426. if (ad->mask == 1) {
  427. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  428. return RLI_ERRORE;
  429. mask_buf = G_malloc(ad->cl * sizeof(int));
  430. if (mask_buf == NULL) {
  431. G_fatal_error("malloc mask_buf failed");
  432. return RLI_ERRORE;
  433. }
  434. masked = TRUE;
  435. }
  436. mask_patch_sup = G_malloc(ad->cl * sizeof(long));
  437. if (mask_patch_sup == NULL) {
  438. G_fatal_error("malloc mask_patch_sup failed");
  439. return RLI_ERRORE;
  440. }
  441. mask_patch_corr = G_malloc(ad->cl * sizeof(long));
  442. if (mask_patch_corr == NULL) {
  443. G_fatal_error("malloc mask_patch_corr failed");
  444. return RLI_ERRORE;
  445. }
  446. buf_sup = Rast_allocate_d_buf();
  447. if (buf_sup == NULL) {
  448. G_fatal_error("malloc buf_sup failed");
  449. return RLI_ERRORE;
  450. }
  451. buf = Rast_allocate_d_buf();
  452. if (buf == NULL) {
  453. G_fatal_error("malloc buf failed");
  454. return RLI_ERRORE;
  455. }
  456. Rast_set_d_null_value(buf_sup + ad->x, ad->cl); /*the first time buf_sup is all null */
  457. for (i = 0; i < ad->cl; i++) {
  458. mask_patch_sup[i] = 0;
  459. mask_patch_corr[i] = 0;
  460. }
  461. /*read each row and put in an avlId tree cell value with the number of cells which have that value */
  462. for (j = 0; j < ad->rl; j++) {
  463. if (j > 0) {
  464. buf_sup = RLI_get_dcell_raster_row(fd, j - 1 + ad->y, ad);
  465. }
  466. buf = RLI_get_dcell_raster_row(fd, j + ad->y, ad);
  467. if (masked) {
  468. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  469. G_fatal_error("mask read failed");
  470. return RLI_ERRORE;
  471. }
  472. }
  473. Rast_set_d_null_value(&precCell, 1);
  474. for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
  475. corrCell = buf[i + ad->x];
  476. if ((masked) && (mask_buf[i + ad->x] == 0)) {
  477. Rast_set_d_null_value(&corrCell, 1);
  478. }
  479. if (!(Rast_is_null_value(&corrCell, DCELL_TYPE))) {
  480. area++;
  481. if (i > 0)
  482. precCell = buf[i - 1 + ad->x];
  483. if (j == 0)
  484. Rast_set_d_null_value(&supCell, 1);
  485. else
  486. supCell = buf_sup[i + ad->x];
  487. if (corrCell != precCell) {
  488. if (corrCell != supCell) {
  489. /*new patch */
  490. if (idCorr == 0) { /*first patch */
  491. lastId = 1;
  492. idCorr = 1;
  493. mask_patch_corr[i] = idCorr;
  494. }
  495. else { /*not first patch */
  496. /* put in the tree previous value */
  497. if (albero == NULL) {
  498. albero = avlID_make(idCorr, uno);
  499. if (albero == NULL) {
  500. G_fatal_error("avlID_make error");
  501. return RLI_ERRORE;
  502. }
  503. npatch++;
  504. }
  505. else { /* tree not null */
  506. ris = avlID_add(&albero, idCorr, uno);
  507. switch (ris) {
  508. case AVL_ERR:
  509. {
  510. G_fatal_error("avlID_add error");
  511. return RLI_ERRORE;
  512. }
  513. case AVL_ADD:
  514. {
  515. npatch++;
  516. break;
  517. }
  518. case AVL_PRES:
  519. {
  520. break;
  521. }
  522. default:
  523. {
  524. G_fatal_error
  525. ("avlID_add unknown error");
  526. return RLI_ERRORE;
  527. }
  528. }
  529. }
  530. lastId++;
  531. idCorr = lastId;
  532. mask_patch_corr[i] = idCorr;
  533. }
  534. }
  535. else { /*current cell and upper cell are equal */
  536. if ((corrCell == precCell) &&
  537. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  538. long r = 0;
  539. long del = mask_patch_sup[i];
  540. /*Remove one patch because it makes part of a patch already found */
  541. r = avlID_sub(&albero, del);
  542. if (r == 0) {
  543. G_fatal_error("avlID_sub error");
  544. return RLI_ERRORE;
  545. }
  546. ris = avlID_add(&albero, idCorr, uno);
  547. switch (ris) {
  548. case AVL_ERR:
  549. {
  550. G_fatal_error("avlID_add error");
  551. return RLI_ERRORE;
  552. }
  553. case AVL_ADD:
  554. {
  555. npatch++;
  556. break;
  557. }
  558. case AVL_PRES:
  559. {
  560. break;
  561. }
  562. default:
  563. {
  564. G_fatal_error("avlID_add unknown error");
  565. return RLI_ERRORE;
  566. }
  567. }
  568. r = i;
  569. while (i < ad->cl) {
  570. if (mask_patch_sup[r] == del) {
  571. mask_patch_sup[r] = idCorr;
  572. }
  573. else {
  574. r = ad->cl + 1;
  575. }
  576. }
  577. }
  578. if (albero == NULL) {
  579. albero = avlID_make(idCorr, uno);
  580. if (albero == NULL) {
  581. G_fatal_error("avlID_make error");
  582. return RLI_ERRORE;
  583. }
  584. npatch++;
  585. }
  586. else { /*tree not null */
  587. ris = avlID_add(&albero, idCorr, uno);
  588. switch (ris) {
  589. case AVL_ERR:
  590. {
  591. G_fatal_error("avlID_add error");
  592. return RLI_ERRORE;
  593. }
  594. case AVL_ADD:
  595. {
  596. npatch++;
  597. break;
  598. }
  599. case AVL_PRES:
  600. {
  601. break;
  602. }
  603. default:
  604. {
  605. G_fatal_error("avlID_add unknown error");
  606. return RLI_ERRORE;
  607. }
  608. }
  609. }
  610. idCorr = mask_patch_sup[i];
  611. mask_patch_corr[i] = idCorr;
  612. }
  613. }
  614. else { /*current cell and previous cell are equals */
  615. if ((corrCell == supCell) &&
  616. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  617. int l;
  618. mask_patch_corr[i] = mask_patch_sup[i];
  619. l = i - 1;
  620. while (l >= 0) {
  621. if (mask_patch_corr[l] == idCorr) {
  622. mask_patch_corr[l] = mask_patch_sup[i];
  623. l--;
  624. }
  625. else {
  626. l = (-1);
  627. }
  628. }
  629. lastId--;
  630. idCorr = mask_patch_sup[i];
  631. }
  632. else {
  633. mask_patch_corr[i] = idCorr;
  634. }
  635. }
  636. }
  637. else { /*cell null or not to consider */
  638. mask_patch_corr[i] = 0;
  639. }
  640. }
  641. mask_patch_sup = mask_patch_corr;
  642. }
  643. if (area != 0) {
  644. if (albero == NULL) {
  645. albero = avlID_make(idCorr, uno);
  646. if (albero == NULL) {
  647. G_fatal_error("avlID_make error");
  648. return RLI_ERRORE;
  649. }
  650. npatch++;
  651. }
  652. else {
  653. ris = avlID_add(&albero, idCorr, uno);
  654. switch (ris) {
  655. case AVL_ERR:
  656. {
  657. G_fatal_error("avlID_add error");
  658. return RLI_ERRORE;
  659. }
  660. case AVL_ADD:
  661. {
  662. npatch++;
  663. break;
  664. }
  665. case AVL_PRES:
  666. {
  667. break;
  668. }
  669. default:
  670. {
  671. G_fatal_error("avlID_add unknown error");
  672. return RLI_ERRORE;
  673. }
  674. }
  675. }
  676. array = G_malloc(npatch * sizeof(avlID_tableRow));
  677. if (array == NULL) {
  678. G_fatal_error("malloc array failed");
  679. return RLI_ERRORE;
  680. }
  681. tot = avlID_to_array(albero, zero, array);
  682. if (tot != npatch) {
  683. G_warning
  684. ("avlID_to_array unaspected value. the result could be wrong");
  685. return RLI_ERRORE;
  686. }
  687. for (i = 0; i < npatch; i++) {
  688. if (array[i]->tot == 0)
  689. doppi++;
  690. }
  691. npatch = npatch - doppi;
  692. /*calculate distance */
  693. G_begin_distance_calculations();
  694. /* EW Dist at North edge */
  695. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  696. /* EW Dist at South Edge */
  697. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  698. /* NS Dist at East edge */
  699. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  700. /* NS Dist at West edge */
  701. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  702. areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  703. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
  704. indice = areaCorrect / npatch;
  705. G_free(array);
  706. }
  707. else
  708. indice = (double)(0);
  709. *result = indice;
  710. if (masked)
  711. G_free(mask_buf);
  712. G_free(mask_patch_corr);
  713. return RLI_OK;
  714. }
  715. int calculateF(int fd, struct area_entry *ad, struct Cell_head hd, double *result)
  716. {
  717. FCELL *buf;
  718. FCELL *buf_sup;
  719. FCELL corrCell;
  720. FCELL precCell;
  721. FCELL supCell;
  722. int i, j;
  723. int mask_fd = -1, *mask_buf;
  724. int ris = 0;
  725. int masked = FALSE;
  726. long npatch = 0;
  727. long tot = 0;
  728. long zero = 0;
  729. long uno = 1;
  730. long idCorr = 0;
  731. long lastId = 0;
  732. long doppi = 0;
  733. long *mask_patch_sup;
  734. long *mask_patch_corr;
  735. double indice = 0;
  736. double area = 0; /*if all cells are null area=0 */
  737. double areaCorrect = 0;
  738. double EW_DIST1, EW_DIST2, NS_DIST1, NS_DIST2;
  739. avlID_tree albero = NULL;
  740. avlID_table *array;
  741. /* open mask if needed */
  742. if (ad->mask == 1) {
  743. if ((mask_fd = open(ad->mask_name, O_RDONLY, 0755)) < 0)
  744. return RLI_ERRORE;
  745. mask_buf = G_malloc(ad->cl * sizeof(int));
  746. if (mask_buf == NULL) {
  747. G_fatal_error("malloc mask_buf failed");
  748. return RLI_ERRORE;
  749. }
  750. masked = TRUE;
  751. }
  752. mask_patch_sup = G_malloc(ad->cl * sizeof(long));
  753. if (mask_patch_sup == NULL) {
  754. G_fatal_error("malloc mask_patch_sup failed");
  755. return RLI_ERRORE;
  756. }
  757. mask_patch_corr = G_malloc(ad->cl * sizeof(long));
  758. if (mask_patch_corr == NULL) {
  759. G_fatal_error("malloc mask_patch_corr failed");
  760. return RLI_ERRORE;
  761. }
  762. buf_sup = Rast_allocate_f_buf();
  763. if (buf_sup == NULL) {
  764. G_fatal_error("malloc buf_sup failed");
  765. return RLI_ERRORE;
  766. }
  767. buf = Rast_allocate_f_buf();
  768. if (buf == NULL) {
  769. G_fatal_error("malloc buf failed");
  770. return RLI_ERRORE;
  771. }
  772. Rast_set_f_null_value(buf_sup + ad->x, ad->cl); /*the first time buf_sup is all null */
  773. for (i = 0; i < ad->cl; i++) {
  774. mask_patch_sup[i] = 0;
  775. mask_patch_corr[i] = 0;
  776. }
  777. /*for each raster row */
  778. for (j = 0; j < ad->rl; j++) {
  779. if (j > 0) {
  780. buf_sup = RLI_get_fcell_raster_row(fd, j - 1 + ad->y, ad);
  781. }
  782. buf = RLI_get_fcell_raster_row(fd, j + ad->y, ad);
  783. if (masked) {
  784. if (read(mask_fd, mask_buf, (ad->cl * sizeof(int))) < 0) {
  785. G_fatal_error("mask read failed");
  786. return RLI_ERRORE;
  787. }
  788. }
  789. Rast_set_f_null_value(&precCell, 1);
  790. for (i = 0; i < ad->cl; i++) { /*for each cell in the row */
  791. corrCell = buf[i + ad->x];
  792. if (((masked) && (mask_buf[i + ad->x] == 0))) {
  793. Rast_set_f_null_value(&corrCell, 1);
  794. }
  795. if (!(Rast_is_null_value(&corrCell, FCELL_TYPE))) {
  796. area++;
  797. if (i > 0)
  798. precCell = buf[i - 1 + ad->x];
  799. if (j == 0)
  800. Rast_set_f_null_value(&supCell, 1);
  801. else
  802. supCell = buf_sup[i + ad->x];
  803. if (corrCell != precCell) {
  804. if (corrCell != supCell) {
  805. /*new patch */
  806. if (idCorr == 0) { /*first patch */
  807. lastId = 1;
  808. idCorr = 1;
  809. mask_patch_corr[i] = idCorr;
  810. }
  811. else { /*not first patch */
  812. /* put in the tree previous value */
  813. if (albero == NULL) {
  814. albero = avlID_make(idCorr, uno);
  815. if (albero == NULL) {
  816. G_fatal_error("avlID_make error");
  817. return RLI_ERRORE;
  818. }
  819. npatch++;
  820. }
  821. else { /*tree not empty */
  822. ris = avlID_add(&albero, idCorr, uno);
  823. switch (ris) {
  824. case AVL_ERR:
  825. {
  826. G_fatal_error("avlID_add error");
  827. return RLI_ERRORE;
  828. }
  829. case AVL_ADD:
  830. {
  831. npatch++;
  832. break;
  833. }
  834. case AVL_PRES:
  835. {
  836. break;
  837. }
  838. default:
  839. {
  840. G_fatal_error
  841. ("avlID_add unknown error");
  842. return RLI_ERRORE;
  843. }
  844. }
  845. }
  846. lastId++;
  847. idCorr = lastId;
  848. mask_patch_corr[i] = idCorr;
  849. }
  850. }
  851. else { /*current cell and upper cell are equal */
  852. if ((corrCell == precCell) &&
  853. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  854. long r = 0;
  855. long del = mask_patch_sup[i];
  856. r = avlID_sub(&albero, del);
  857. if (r == 0) {
  858. G_fatal_error("avlID_sub error");
  859. return RLI_ERRORE;
  860. }
  861. /*Remove one patch because it makes part of a patch already found */
  862. ris = avlID_add(&albero, idCorr, uno);
  863. switch (ris) {
  864. case AVL_ERR:
  865. {
  866. G_fatal_error("avlID_add error");
  867. return RLI_ERRORE;
  868. }
  869. case AVL_ADD:
  870. {
  871. npatch++;
  872. break;
  873. }
  874. case AVL_PRES:
  875. {
  876. break;
  877. }
  878. default:
  879. {
  880. G_fatal_error("avlID_add unknown error");
  881. return RLI_ERRORE;
  882. }
  883. }
  884. r = i;
  885. while (i < ad->cl) {
  886. if (mask_patch_sup[r] == del) {
  887. mask_patch_sup[r] = idCorr;
  888. }
  889. else {
  890. r = ad->cl + 1;
  891. }
  892. }
  893. }
  894. if (albero == NULL) {
  895. albero = avlID_make(idCorr, uno);
  896. if (albero == NULL) {
  897. G_fatal_error("avlID_make error");
  898. return RLI_ERRORE;
  899. }
  900. npatch++;
  901. }
  902. else { /*the tree (albero) isn't null */
  903. ris = avlID_add(&albero, idCorr, uno);
  904. switch (ris) {
  905. case AVL_ERR:
  906. {
  907. G_fatal_error("avlID_add error");
  908. return RLI_ERRORE;
  909. }
  910. case AVL_ADD:
  911. {
  912. npatch++;
  913. break;
  914. }
  915. case AVL_PRES:
  916. {
  917. break;
  918. }
  919. default:
  920. {
  921. G_fatal_error("avlID_add unknown error");
  922. return RLI_ERRORE;
  923. }
  924. }
  925. }
  926. idCorr = mask_patch_sup[i];
  927. mask_patch_corr[i] = idCorr;
  928. }
  929. }
  930. else { /*current cell and previous cell are equal */
  931. if ((corrCell == supCell) &&
  932. (mask_patch_sup[i] != mask_patch_corr[i - 1])) {
  933. int l;
  934. mask_patch_corr[i] = mask_patch_sup[i];
  935. l = i - 1;
  936. while (l >= 0) {
  937. if (mask_patch_corr[l] == idCorr) {
  938. mask_patch_corr[l] = mask_patch_sup[i];
  939. l--;
  940. }
  941. else {
  942. l = (-1);
  943. }
  944. }
  945. lastId--;
  946. idCorr = mask_patch_sup[i];
  947. }
  948. else {
  949. mask_patch_corr[i] = idCorr;
  950. }
  951. }
  952. }
  953. else { /*null cell or cell not to consider */
  954. mask_patch_corr[i] = 0;
  955. }
  956. }
  957. mask_patch_sup = mask_patch_corr;
  958. }
  959. if (area != 0) {
  960. if (albero == NULL) {
  961. albero = avlID_make(idCorr, uno);
  962. if (albero == NULL) {
  963. G_fatal_error("avlID_make error");
  964. return RLI_ERRORE;
  965. }
  966. npatch++;
  967. }
  968. else {
  969. ris = avlID_add(&albero, idCorr, uno);
  970. switch (ris) {
  971. case AVL_ERR:
  972. {
  973. G_fatal_error("avlID_add error");
  974. return RLI_ERRORE;
  975. }
  976. case AVL_ADD:
  977. {
  978. npatch++;
  979. break;
  980. }
  981. case AVL_PRES:
  982. {
  983. break;
  984. }
  985. default:
  986. {
  987. G_fatal_error("avlID_add unknown error");
  988. return RLI_ERRORE;
  989. }
  990. }
  991. }
  992. array = G_malloc(npatch * sizeof(avlID_tableRow));
  993. if (array == NULL) {
  994. G_fatal_error("malloc array failed");
  995. return RLI_ERRORE;
  996. }
  997. tot = avlID_to_array(albero, zero, array);
  998. if (tot != npatch) {
  999. G_warning
  1000. ("avlID_to_array unaspected value. the result could be wrong");
  1001. return RLI_ERRORE;
  1002. }
  1003. for (i = 0; i < npatch; i++) {
  1004. if (array[i]->tot == 0)
  1005. doppi++;
  1006. }
  1007. npatch = npatch - doppi;
  1008. /*calculate distance */
  1009. G_begin_distance_calculations();
  1010. /* EW Dist at North edge */
  1011. EW_DIST1 = G_distance(hd.east, hd.north, hd.west, hd.north);
  1012. /* EW Dist at South Edge */
  1013. EW_DIST2 = G_distance(hd.east, hd.south, hd.west, hd.south);
  1014. /* NS Dist at East edge */
  1015. NS_DIST1 = G_distance(hd.east, hd.north, hd.east, hd.south);
  1016. /* NS Dist at West edge */
  1017. NS_DIST2 = G_distance(hd.west, hd.north, hd.west, hd.south);
  1018. areaCorrect = (((EW_DIST1 + EW_DIST2) / 2) / hd.cols) *
  1019. (((NS_DIST1 + NS_DIST2) / 2) / hd.rows) * (area);
  1020. indice = areaCorrect / npatch;
  1021. G_free(array);
  1022. }
  1023. else
  1024. indice = (double)(0);
  1025. *result = indice;
  1026. if (masked)
  1027. G_free(mask_buf);
  1028. G_free(mask_patch_corr);
  1029. return RLI_OK;
  1030. }