texture.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. /*
  2. ************************************************************
  3. * MODULE: r.le.pixel/texture.c *
  4. * Version 5.0 Nov. 1, 2001 *
  5. * *
  6. * AUTHOR: W.L. Baker, University of Wyoming *
  7. * BAKERWL@UWYO.EDU *
  8. * *
  9. * PURPOSE: To analyze pixel-scale landscape properties *
  10. * texture.c calculates the measures for r.le.pixel *
  11. * *
  12. * COPYRIGHT: (C) 2001 by W.L. Baker *
  13. * *
  14. * This program is free software under the GNU General *
  15. * Public License(>=v2). Read the file COPYING that comes *
  16. * with GRASS for details *
  17. * *
  18. ************************************************************/
  19. #include <grass/gis.h>
  20. #include <grass/config.h>
  21. #include <grass/raster.h>
  22. #include "pixel.h"
  23. /* set the maximum number of categories
  24. that can be in the input map */
  25. #define NO_OF_CATEGORIES cats.num
  26. /* set external pointers and routines */
  27. extern struct CHOICE *choice;
  28. extern int g_scale, g_unit;
  29. /* define a structure used to read in
  30. info about categories in the map */
  31. struct Categories cats;
  32. /* declare a counter for the number
  33. of pixels with non-null values
  34. (total) in cal_edge and a flag for
  35. pixels with null attribute in
  36. cal_divers */
  37. int total, nullflag;
  38. /* MOVING WINDOW ANALYSIS DRIVER */
  39. void mv_texture(int nrows, int ncols, double **buf, double **null_buf,
  40. double **value, int index, double *rich, int cnt,
  41. int cntwhole)
  42. {
  43. int lc;
  44. register int i, j;
  45. double *atts, *edgeatts, attr[4], diver[4], edge[4], tex[5], **weight,
  46. **edgemat;
  47. /* set the contents of the arrays used
  48. used to stored the results of the
  49. diversity, texture, and edge
  50. calculations to zero */
  51. attr[0] = attr[1] = attr[2] = attr[3] = 0;
  52. diver[0] = diver[1] = diver[2] = diver[3] = 0;
  53. tex[0] = tex[1] = tex[2] = tex[3] = tex[4] = 0;
  54. edge[0] = edge[1] = edge[2] = edge[3] = 0;
  55. /*************************/
  56. /* The weight matrix in */
  57. /* "r.le.para/weight" */
  58. /* must have the follow- */
  59. /* ing format: a, b, c */
  60. /* = category values */
  61. /* */
  62. /* a b c */
  63. /* a 0.0 0.1 0.1 */
  64. /* b 0.1 0.1 0.1 */
  65. /* c 0.2 0.2 0.3 */
  66. /*************************/
  67. /* If juxtaposition is to be
  68. calculated, then dynamically
  69. allocate memory for the atts
  70. array and the weight matrix */
  71. if (choice->jux[0]) {
  72. atts = (double *)G_calloc(cntwhole, sizeof(double));
  73. weight = (double **)G_calloc(cntwhole, sizeof(double *));
  74. for (i = 0; i < cntwhole; i++)
  75. weight[i] = (double *)G_calloc(cntwhole, sizeof(double));
  76. /* read in the weight matrix */
  77. read_weight(cntwhole, atts, weight);
  78. total = 0;
  79. }
  80. /*************************/
  81. /* The edge matrix in */
  82. /* "r.le.para/edge" */
  83. /* must have the follow- */
  84. /* ing format: a, b, c */
  85. /* = category values */
  86. /* */
  87. /* a b c */
  88. /* a 0 1 1 */
  89. /* b 1 0 1 */
  90. /* c 1 1 0 */
  91. /*************************/
  92. /* If edge by type is to be
  93. calculated, then dynamically
  94. allocate memory for the edgeatts
  95. array and the edgemat matrix */
  96. if (choice->edg[2]) {
  97. edgeatts = (double *)G_malloc(cntwhole * sizeof(double));
  98. edgemat = (double **)G_malloc(cntwhole * sizeof(double *));
  99. for (i = 0; i < cntwhole; i++)
  100. edgemat[i] = (double *)G_malloc(cntwhole * sizeof(double));
  101. /* read in the edge matrix */
  102. read_edge(cntwhole, edgeatts, edgemat);
  103. }
  104. /* main calculation loop. Do the
  105. calculations for each pixel in
  106. the sampling area */
  107. for (i = 1; i < nrows + 1; i++) {
  108. for (j = 1; j < ncols + 1; j++) {
  109. /* find the sequence number of the
  110. attribute in the richness array */
  111. if ((buf[i][j] || buf[i][j] == 0.0) && null_buf[i][j] == 0.0)
  112. lc = check_order(buf[i][j], rich);
  113. /* based on the choices made, call
  114. the appropriate calc. routine */
  115. if (choice->att[0])
  116. cal_att(buf, null_buf, i, j, nrows, ncols, attr);
  117. if (choice->te2[0])
  118. cal_tex(buf, null_buf, i, j, nrows, ncols, lc, rich, cnt,
  119. tex);
  120. if (choice->edg[0] || choice->jux[0])
  121. cal_edge(buf, null_buf, i, j, nrows, ncols, lc, edge,
  122. cntwhole, atts, weight, edgeatts, edgemat, 0, 0);
  123. if (choice->div[0])
  124. cal_divers(buf, null_buf, i, j, nrows, ncols, lc, cnt, diver);
  125. }
  126. }
  127. if (choice->jux[0]) {
  128. G_free(atts);
  129. for (i = 0; i < cntwhole; i++)
  130. G_free(weight[i]);
  131. G_free(weight);
  132. }
  133. if (choice->edg[2]) {
  134. G_free(edgeatts);
  135. for (i = 0; i < cntwhole; i++)
  136. G_free(edgemat[i]);
  137. G_free(edgemat);
  138. }
  139. /* put the calculated value for the
  140. selected measure into the
  141. corresponding pixel in the output
  142. map */
  143. if (choice->att[0]) { /* ATTRIBUTE MEASURES */
  144. if (choice->att[1])
  145. value[index][0] = attr[0]; /* Mean */
  146. if (choice->att[2])
  147. value[index][1] = attr[1]; /* St. dev. */
  148. if (choice->att[3])
  149. value[index][2] = attr[2]; /* Min. */
  150. if (choice->att[4])
  151. value[index][3] = attr[3]; /* Max. */
  152. }
  153. if (choice->div[0]) { /* DIVERSITY MEASURES */
  154. if (choice->div[1])
  155. value[index][4] = diver[0]; /* Richness */
  156. if (choice->div[2])
  157. value[index][5] = diver[1]; /* Shannon */
  158. if (choice->div[3])
  159. value[index][6] = diver[2]; /* Dominance */
  160. if (choice->div[4])
  161. value[index][7] = diver[3]; /* Inv. Simpson */
  162. }
  163. if (choice->te2) { /* TEXTURE MEASURES */
  164. if (choice->te2[1]) /* Contagion */
  165. value[index][8] = tex[0];
  166. if (choice->te2[2]) /* ASM */
  167. value[index][9] = tex[1];
  168. if (choice->te2[3]) /* IDM */
  169. value[index][10] = tex[2];
  170. if (choice->te2[4]) /* Entropy */
  171. value[index][11] = tex[3];
  172. if (choice->te2[5]) /* Contrast */
  173. value[index][12] = tex[4];
  174. }
  175. if (choice->jux[0]) { /* JUXTA. MEASURES */
  176. if (choice->jux[1])
  177. value[index][13] = edge[0]; /* Mean jux. */
  178. if (choice->jux[2])
  179. value[index][14] = edge[2]; /* St.dev. jux. */
  180. }
  181. if (choice->edg[0]) { /* EDGE MEASURES */
  182. if (choice->edg[1])
  183. value[index][15] = edge[1]; /* Sum of edges */
  184. if (choice->edg[2])
  185. value[index][16] = edge[3]; /* Sum of edges
  186. by type */
  187. }
  188. return;
  189. }
  190. /* WHOLE MAP, UNITS, OR REGIONS
  191. DRIVER */
  192. void df_texture(int nrows, int ncols, double **buf, double **null_buf,
  193. double *rich, int cnt, int cntwhole)
  194. {
  195. FILE *fp0, *fp1, *fp2, *fp3, *fp4, *fp5;
  196. int lc, fd, *edge1, *edge2, fc, **edgenull;
  197. register int i, j;
  198. double *atts, *edgeatts, attr[4], diver[4], edge[4], tex[5], **weight,
  199. **edgemat;
  200. CELL **edgemap_c, *edge_buf_c;
  201. FCELL **edgemap_f, *edge_buf_f;
  202. DCELL **edgemap_d, *edge_buf_d, *zscor_buf;
  203. RASTER_MAP_TYPE data_type;
  204. data_type = Rast_map_type(choice->fn, G_mapset());
  205. /* set the contents of the arrays
  206. used to stored the results of the
  207. diversity, texture, and edge
  208. calculations to zero */
  209. attr[0] = attr[1] = attr[2] = attr[3] = 0;
  210. diver[0] = diver[1] = diver[2] = diver[3] = 0;
  211. edge[0] = edge[1] = edge[2] = edge[3] = 0;
  212. tex[0] = tex[1] = tex[2] = tex[3] = tex[4] = 0;
  213. /*************************/
  214. /* The weight matrix in */
  215. /* "r.le.para/weight" */
  216. /* must have the follow- */
  217. /* ing format: a, b, c */
  218. /* = category values */
  219. /* */
  220. /* a b c */
  221. /* a 0.0 0.1 0.1 */
  222. /* b 0.1 0.1 0.1 */
  223. /* c 0.2 0.2 0.3 */
  224. /*************************/
  225. /* If juxtaposition is to be
  226. calculated, then dynamically
  227. allocate memory for the atts
  228. array and the weight matrix */
  229. if (choice->jux[0]) {
  230. atts = (double *)G_calloc(cntwhole, sizeof(double));
  231. weight = (double **)G_calloc(cntwhole, sizeof(double *));
  232. for (i = 0; i < cntwhole; i++)
  233. weight[i] = (double *)G_calloc(cntwhole, sizeof(double));
  234. /* read in the weight matrix */
  235. read_weight(cntwhole, atts, weight);
  236. total = 0;
  237. }
  238. /*************************/
  239. /* The edge matrix in */
  240. /* "r.le.para/edge" */
  241. /* must have the follow- */
  242. /* ing format: a, b, c */
  243. /* = category values */
  244. /* */
  245. /* a b c */
  246. /* a 0 1 1 */
  247. /* b 1 0 1 */
  248. /* c 1 1 0 */
  249. /*************************/
  250. /* If edge by type is to be
  251. calculated, then dynamically
  252. allocate memory for the edgeatts
  253. array and the edgemat matrix */
  254. if (choice->edg[2]) {
  255. edgeatts = (double *)G_calloc(cntwhole, sizeof(double));
  256. edgemat = (double **)G_calloc(cntwhole, sizeof(double *));
  257. for (i = 0; i < cntwhole; i++) {
  258. edgemat[i] = (double *)G_calloc(cntwhole, sizeof(double));
  259. }
  260. /* read in the edge matrix */
  261. read_edge(cntwhole, edgeatts, edgemat);
  262. }
  263. /* dynamically allocate storage for the
  264. buffer that will hold the map of the
  265. edges and for the edgenull array */
  266. if (choice->edgemap) {
  267. switch (data_type) {
  268. case (CELL_TYPE):
  269. edgemap_c = (CELL **) G_calloc(nrows + 3, sizeof(CELL *));
  270. for (i = 0; i < nrows + 3; i++)
  271. edgemap_c[i] = (CELL *) G_calloc(ncols + 3, sizeof(CELL));
  272. break;
  273. case (FCELL_TYPE):
  274. edgemap_f = (FCELL **) G_calloc(nrows + 3, sizeof(FCELL *));
  275. for (i = 0; i < nrows + 3; i++)
  276. edgemap_f[i] = (FCELL *) G_calloc(ncols + 3, sizeof(FCELL));
  277. break;
  278. case (DCELL_TYPE):
  279. edgemap_d = (DCELL **) G_calloc(nrows + 3, sizeof(DCELL *));
  280. for (i = 0; i < nrows + 3; i++)
  281. edgemap_d[i] = (DCELL *) G_calloc(ncols + 3, sizeof(DCELL));
  282. break;
  283. }
  284. edgenull = (int **)G_calloc(nrows + 3, sizeof(int *));
  285. for (i = 0; i < nrows + 3; i++) {
  286. edgenull[i] = (int *)G_calloc(ncols + 3, sizeof(int));
  287. }
  288. for (i = 1; i < nrows + 1; i++)
  289. for (j = 1; j < ncols + 1; j++)
  290. *(*(edgenull + i) + j) = 1;
  291. }
  292. /* main calculation loop. Do the
  293. calculations for each pixel in
  294. the map */
  295. for (i = 1; i < nrows + 1; i++) {
  296. for (j = 1; j < ncols + 1; j++) {
  297. /* find the sequence number of the
  298. attribute in the richness array */
  299. if ((buf[i][j] || buf[i][j] == 0.0) && null_buf[i][j] == 0.0)
  300. lc = check_order(buf[i][j], rich);
  301. /* based on the choices made, call
  302. the appropriate calc. routine */
  303. if (choice->att[0])
  304. cal_att(buf, null_buf, i, j, nrows, ncols, attr);
  305. if (choice->div[0])
  306. cal_divers(buf, null_buf, i, j, nrows, ncols, lc, cnt, diver);
  307. if (choice->jux[0] || choice->edg[0]) {
  308. edge1 = edge2 = 0;
  309. cal_edge(buf, null_buf, i, j, nrows, ncols, lc, edge,
  310. cntwhole, atts, weight, edgeatts, edgemat, &edge1,
  311. &edge2);
  312. if (choice->edgemap) {
  313. if (edge1) {
  314. switch (data_type) {
  315. case (CELL_TYPE):
  316. *(*(edgemap_c + i) + j) = *(*(buf + i) + j);
  317. *(*(edgemap_c + i + 1) + j) =
  318. *(*(buf + i + 1) + j);
  319. break;
  320. case (FCELL_TYPE):
  321. *(*(edgemap_f + i) + j) = *(*(buf + i) + j);
  322. *(*(edgemap_f + i + 1) + j) =
  323. *(*(buf + i + 1) + j);
  324. break;
  325. case (DCELL_TYPE):
  326. *(*(edgemap_d + i) + j) = *(*(buf + i) + j);
  327. *(*(edgemap_d + i + 1) + j) =
  328. *(*(buf + i + 1) + j);
  329. break;
  330. }
  331. *(*(edgenull + i) + j) = 0;
  332. *(*(edgenull + i + 1) + j) = 0;
  333. }
  334. if (edge2) {
  335. switch (data_type) {
  336. case (CELL_TYPE):
  337. *(*(edgemap_c + i) + j) = *(*(buf + i) + j);
  338. *(*(edgemap_c + i) + j + 1) =
  339. *(*(buf + i) + j + 1);
  340. break;
  341. case (FCELL_TYPE):
  342. *(*(edgemap_f + i) + j) = *(*(buf + i) + j);
  343. *(*(edgemap_f + i) + j + 1) =
  344. *(*(buf + i) + j + 1);
  345. break;
  346. case (DCELL_TYPE):
  347. *(*(edgemap_d + i) + j) = *(*(buf + i) + j);
  348. *(*(edgemap_d + i) + j + 1) =
  349. *(*(buf + i) + j + 1);
  350. break;
  351. }
  352. *(*(edgenull + i) + j) = 0;
  353. *(*(edgenull + i) + j + 1) = 0;
  354. }
  355. }
  356. }
  357. if (choice->te2[0])
  358. cal_tex(buf, null_buf, i, j, nrows, ncols, lc, rich, cnt,
  359. tex);
  360. }
  361. }
  362. if (choice->jux[0]) {
  363. G_free(atts);
  364. for (i = 0; i < cntwhole; i++)
  365. G_free(weight[i]);
  366. G_free(weight);
  367. }
  368. if (choice->edg[2]) {
  369. G_free(edgeatts);
  370. for (i = 0; i < cntwhole; i++)
  371. G_free(edgemat[i]);
  372. G_free(edgemat);
  373. }
  374. /* if the edge map was requested */
  375. if (choice->edgemap) {
  376. fc = Rast_open_new("edge", data_type);
  377. switch (data_type) {
  378. case (CELL_TYPE):
  379. edge_buf_c = Rast_allocate_buf(CELL_TYPE);
  380. for (i = 1; i < nrows + 1; i++) {
  381. Rast_zero_buf(edge_buf_c, CELL_TYPE);
  382. Rast_set_null_value(edge_buf_c, ncols + 1, CELL_TYPE);
  383. for (j = 1; j < ncols + 1; j++) {
  384. if (*(*(edgenull + i) + j) == 0)
  385. *(edge_buf_c + j - 1) = edgemap_c[i][j];
  386. }
  387. Rast_put_row(fc, edge_buf_c, CELL_TYPE);
  388. }
  389. break;
  390. case (FCELL_TYPE):
  391. edge_buf_f = Rast_allocate_buf(FCELL_TYPE);
  392. for (i = 1; i < nrows + 1; i++) {
  393. Rast_zero_buf(edge_buf_f, FCELL_TYPE);
  394. Rast_set_null_value(edge_buf_f, ncols + 1, FCELL_TYPE);
  395. for (j = 1; j < ncols + 1; j++) {
  396. if (*(*(edgenull + i) + j) == 0)
  397. *(edge_buf_f + j - 1) = edgemap_f[i][j];
  398. }
  399. Rast_put_row(fc, edge_buf_f, FCELL_TYPE);
  400. }
  401. break;
  402. case (DCELL_TYPE):
  403. edge_buf_d = Rast_allocate_buf(DCELL_TYPE);
  404. for (i = 1; i < nrows + 1; i++) {
  405. Rast_zero_buf(edge_buf_d, DCELL_TYPE);
  406. Rast_set_null_value(edge_buf_d, ncols + 1, DCELL_TYPE);
  407. for (j = 1; j < ncols + 1; j++) {
  408. if (*(*(edgenull + i) + j) == 0)
  409. *(edge_buf_d + j - 1) = edgemap_d[i][j];
  410. }
  411. Rast_put_row(fc, edge_buf_d, DCELL_TYPE);
  412. }
  413. break;
  414. }
  415. switch (data_type) {
  416. case (CELL_TYPE):
  417. G_free(edge_buf_c);
  418. for (i = 0; i < nrows + 3; i++)
  419. G_free(edgemap_c[i]);
  420. G_free(edgemap_c);
  421. break;
  422. case (FCELL_TYPE):
  423. G_free(edge_buf_f);
  424. for (i = 0; i < nrows + 3; i++)
  425. G_free(edgemap_f[i]);
  426. G_free(edgemap_f);
  427. break;
  428. case (DCELL_TYPE):
  429. G_free(edge_buf_d);
  430. for (i = 0; i < nrows + 3; i++)
  431. G_free(edgemap_d[i]);
  432. G_free(edgemap_d);
  433. break;
  434. }
  435. for (i = 0; i < nrows + 3; i++)
  436. G_free(edgenull[i]);
  437. G_free(edgenull);
  438. Rast_close(fc);
  439. }
  440. /* if the zscore map was requested */
  441. if (choice->z) {
  442. fd = Rast_open_new("zscores", DCELL_TYPE);
  443. zscor_buf = Rast_allocate_buf(DCELL_TYPE);
  444. for (i = 1; i < nrows + 1; i++) {
  445. Rast_zero_buf(zscor_buf, DCELL_TYPE);
  446. Rast_set_null_value(zscor_buf, ncols + 1, DCELL_TYPE);
  447. for (j = 1; j < ncols + 1; j++) {
  448. if (attr[1] > 0.0)
  449. if ((buf[i][j] || buf[i][j] == 0) &&
  450. null_buf[i][j] == 0.0)
  451. *(zscor_buf + j - 1) =
  452. (buf[i][j] - attr[0]) / attr[1];
  453. }
  454. Rast_put_row(fd, zscor_buf, DCELL_TYPE);
  455. }
  456. G_free(zscor_buf);
  457. Rast_close(fd);
  458. }
  459. /* open the output files and
  460. save the calculated values */
  461. if (choice->att[0]) {
  462. fp0 = fopen0("r.le.out/b1-4.out", "a");
  463. fprintf(fp0, "%5d%5d", g_scale, g_unit);
  464. fprintf(fp0, " %10.3f %10.3f %10.3f %10.3f\n",
  465. attr[0], attr[1], attr[2], attr[3]);
  466. fclose(fp0);
  467. }
  468. if (choice->div[0]) {
  469. fp1 = fopen0("r.le.out/d1-4.out", "a");
  470. fprintf(fp1, "%5d%5d", g_scale, g_unit);
  471. fprintf(fp1, " %10.3f %10.3f %10.3f %10.3f\n",
  472. diver[0], diver[1], diver[2], diver[3]);
  473. fclose(fp1);
  474. }
  475. if (choice->te2[0]) {
  476. fp2 = fopen0("r.le.out/t1-5.out", "a");
  477. fprintf(fp2, "%5d%5d", g_scale, g_unit);
  478. fprintf(fp2, " %10.3f %10.3f %10.3f %10.3f %10.3f\n",
  479. tex[0], tex[1], tex[2], tex[3], tex[4]);
  480. fclose(fp2);
  481. }
  482. if (choice->jux[0]) {
  483. fp3 = fopen0("r.le.out/j1-2.out", "a");
  484. fprintf(fp3, "%5d%5d", g_scale, g_unit);
  485. fprintf(fp3, " %10.3f %10.3f\n", edge[0], edge[2]);
  486. fclose(fp3);
  487. }
  488. if (choice->edg[1]) {
  489. fp4 = fopen0("r.le.out/e1.out", "a");
  490. fprintf(fp4, "%5d%5d", g_scale, g_unit);
  491. fprintf(fp4, " %10.0f\n", edge[1]);
  492. fclose(fp4);
  493. }
  494. if (choice->edg[2]) {
  495. fp5 = fopen0("r.le.out/e2.out", "a");
  496. fprintf(fp5, "%5d%5d", g_scale, g_unit);
  497. fprintf(fp5, " %10.0f\n", edge[3]);
  498. fclose(fp5);
  499. }
  500. return;
  501. }
  502. /* ATTRIBUTE CALC. */
  503. void cal_att(double **buf, double **null_buf, int i0, int j0, int nr, int nc,
  504. double *attr)
  505. {
  506. static int count;
  507. static double mini, maxi;
  508. double mean, stdv;
  509. static double sum, sum2;
  510. if (i0 == 1 && j0 == 1) {
  511. sum = 0.0;
  512. sum2 = 0.0;
  513. count = 0;
  514. maxi = 0.0;
  515. mini = BIG;
  516. mean = 0.0;
  517. stdv = 0.0;
  518. }
  519. if ((buf[i0][j0] || buf[i0][j0] == 0.0) && null_buf[i0][j0] == 0.0) {
  520. count++;
  521. sum += buf[i0][j0];
  522. sum2 += buf[i0][j0] * buf[i0][j0];
  523. if (buf[i0][j0] > maxi)
  524. maxi = buf[i0][j0];
  525. if (buf[i0][j0] < mini)
  526. mini = buf[i0][j0];
  527. }
  528. if (i0 == nr && j0 == nc) {
  529. /* calc. b1 = mean pixel attr. */
  530. attr[0] = mean = sum / count;
  531. /* calc. b2 = st. dev. pixel attr. */
  532. stdv = sum2 / count - mean * mean;
  533. if (stdv > 0)
  534. attr[1] = sqrt(stdv);
  535. /* calc. b3 = min. pixel attr. */
  536. attr[2] = mini;
  537. /* calc. b4 = max. pixel attr. */
  538. attr[3] = maxi;
  539. }
  540. return;
  541. }
  542. /* DIVERSITY CALC. */
  543. void cal_divers(double **buf, double **null_buf, int i0, int j0, int nr,
  544. int nc, int lc, int cnt, double *diver)
  545. {
  546. int tot;
  547. static int *density;
  548. register int i;
  549. double p, entr;
  550. /* if this is the first pixel,
  551. dynamically allocate memory for
  552. the density array */
  553. if (1 == i0 && 1 == j0)
  554. density = (int *)G_calloc(cnt, sizeof(int));
  555. /* if the pixel has a non-null
  556. attribute */
  557. if ((buf[i0][j0] || buf[i0][j0] == 0) && null_buf[i0][j0] == 0.0) {
  558. /* increment the density count for
  559. the right element of the density
  560. array */
  561. density[lc]++;
  562. }
  563. /* if this is the last pixel in the
  564. sampling area, do the calc. */
  565. if (i0 == nr && j0 == nc) {
  566. /* initialize the counter for the
  567. total number of pixels */
  568. tot = 0;
  569. diver[0] = cnt; /* richness */
  570. if (cnt > 1)
  571. entr = log((double)(cnt));
  572. else
  573. entr = 0.0;
  574. /* calculate the total # of pixels */
  575. for (i = 0; i < cnt; i++) {
  576. /*printf("i=%d tot=%d density[%d]=%d\n",i,tot,i,density[i]); */
  577. tot = tot + density[i];
  578. }
  579. for (i = 0; i < cnt; i++) {
  580. if (density[i] > 0 && tot > 0) {
  581. p = density[i] / (double)(tot);
  582. diver[1] += -(p * log(p)); /* Shannon */
  583. /*printf("i=%d p=%f shann=%f\n", i, p, diver[1]); */
  584. diver[3] += p * p;
  585. }
  586. }
  587. diver[2] = entr - diver[1]; /* dominance */
  588. diver[3] = 1 / diver[3]; /* recip. Simpson */
  589. G_free(density);
  590. }
  591. return;
  592. }
  593. /* TEXTURE CALC. */
  594. void cal_tex(double **buf, double **null_buf, int i0, int j0, int nr, int nc,
  595. int lc, double *rich, int cnt, double *tex)
  596. {
  597. int r, ln;
  598. double p;
  599. static int **GLCM;
  600. register int i, j;
  601. int GLCM_sum = 0;
  602. /* setup the GLCM matrix */
  603. if ((i0 == 1 && j0 == 1)) {
  604. GLCM = (int **)G_calloc(cnt, sizeof(int *));
  605. for (i = 0; i < cnt; i++)
  606. GLCM[i] = (int *)G_calloc(cnt, sizeof(int));
  607. }
  608. /* calculate the GLCM, using
  609. the appropriate one of the
  610. seven texture methods
  611. (parameter te1) */
  612. if ((buf[i0][j0] || buf[i0][j0] == 0.0) && null_buf[i0][j0] == 0.0) {
  613. if (i0 > 1) {
  614. if (choice->tex == 3 || choice->tex == 5 || choice->tex == 7) {
  615. if ((buf[i0 - 1][j0] ||
  616. buf[i0 - 1][j0] == 0.0) && null_buf[i0 - 1][j0] == 0.0) {
  617. ln = check_order(buf[i0 - 1][j0], rich);
  618. GLCM[lc][ln]++;
  619. }
  620. }
  621. if (j0 > 1 && (choice->tex == 4 ||
  622. choice->tex == 6 || choice->tex == 7)) {
  623. if ((buf[i0 - 1][j0 - 1] ||
  624. buf[i0 - 1][j0 - 1] == 0.0) &&
  625. null_buf[i0 - 1][j0 - 1] == 0.0) {
  626. ln = check_order(buf[i0 - 1][j0 - 1], rich);
  627. GLCM[lc][ln]++;
  628. }
  629. }
  630. if (j0 < nc && (choice->tex == 2 ||
  631. choice->tex == 6 || choice->tex == 7)) {
  632. if ((buf[i0 - 1][j0 + 1] ||
  633. buf[i0 - 1][j0 + 1] == 0.0) &&
  634. null_buf[i0 - 1][j0 + 1] == 0.0) {
  635. ln = check_order(buf[i0 - 1][j0 + 1], rich);
  636. GLCM[lc][ln]++;
  637. }
  638. }
  639. }
  640. if (i0 < nr) {
  641. if (choice->tex == 3 || choice->tex == 5 || choice->tex == 7) {
  642. if ((buf[i0 + 1][j0] ||
  643. buf[i0 + 1][j0] == 0.0) && null_buf[i0 + 1][j0] == 0.0) {
  644. ln = check_order(buf[i0 + 1][j0], rich);
  645. GLCM[lc][ln]++;
  646. }
  647. }
  648. if (j0 > 1 && (choice->tex == 2 ||
  649. choice->tex == 6 || choice->tex == 7)) {
  650. if ((buf[i0 + 1][j0 - 1] ||
  651. buf[i0 + 1][j0 - 1] == 0.0) &&
  652. null_buf[i0 + 1][j0 - 1] == 0.0) {
  653. ln = check_order(buf[i0 + 1][j0 - 1], rich);
  654. GLCM[lc][ln]++;
  655. }
  656. }
  657. if (j0 < nc && (choice->tex == 4 ||
  658. choice->tex == 6 || choice->tex == 7)) {
  659. if ((buf[i0 + 1][j0 + 1] ||
  660. buf[i0 + 1][j0 + 1] == 0.0) &&
  661. null_buf[i0 + 1][j0 + 1] == 0.0) {
  662. ln = check_order(buf[i0 + 1][j0 + 1], rich);
  663. GLCM[lc][ln]++;
  664. }
  665. }
  666. }
  667. if (j0 > 1 && (choice->tex == 1 ||
  668. choice->tex == 5 || choice->tex == 7)) {
  669. if ((buf[i0][j0 - 1] ||
  670. buf[i0][j0 - 1] == 0.0) && null_buf[i0][j0 - 1] == 0.0) {
  671. ln = check_order(buf[i0][j0 - 1], rich);
  672. GLCM[lc][ln]++;
  673. }
  674. }
  675. if (j0 < nc && (choice->tex == 1 ||
  676. choice->tex == 5 || choice->tex == 7)) {
  677. if ((buf[i0][j0 + 1] ||
  678. buf[i0][j0 + 1] == 0.0) && null_buf[i0][j0 + 1] == 0.0) {
  679. ln = check_order(buf[i0][j0 + 1], rich);
  680. GLCM[lc][ln]++;
  681. }
  682. }
  683. }
  684. /* once the end of the buffer
  685. has been reached, sum up the
  686. contents of the GLCM */
  687. if (i0 == nr && j0 == nc) {
  688. for (i = 0; i < cnt; i++) {
  689. /*printf("%3d %3d %3d %3d %3d\n",GLCM[i][0],GLCM[i][1],GLCM[i][2],
  690. GLCM[i][3],GLCM[i][4]); */
  691. for (j = 0; j < cnt; j++)
  692. GLCM_sum = GLCM_sum + GLCM[i][j];
  693. }
  694. r = GLCM_sum;
  695. /* for each category, compute the
  696. Pij and the measures */
  697. for (i = 0; i < cnt; i++)
  698. for (j = 0; j < cnt; j++)
  699. if (p = GLCM[i][j] / (double)(r)) {
  700. tex[3] += p * log(p);
  701. tex[1] += p * p; /* ASM */
  702. tex[2] += p / (1 + (rich[i] - rich[j]) * (rich[i] - rich[j])); /* IDM */
  703. tex[4] += p * (rich[i] - rich[j]) * (rich[i] - rich[j]); /* Contrast */
  704. }
  705. if (tex[3])
  706. tex[3] = -1.0 * tex[3]; /* Entropy */
  707. tex[0] = 2 * log((double)(cnt)) - tex[3]; /* Contagion */
  708. for (i = 0; i < cnt; i++)
  709. G_free(GLCM[i]);
  710. G_free(GLCM);
  711. }
  712. return;
  713. }
  714. /* EDGE, JUXTAPOSITION CALC. */
  715. void cal_edge(double **buf, double **null_buf, int i0, int j0, int nr, int nc,
  716. int lc, double *edge, int cntwhole, double *atts,
  717. double **weight, double *edgeatts, double **edgemat, int *edge1,
  718. int *edge2)
  719. {
  720. int ln, lr, cnt, fr, to;
  721. double juxta, sum, stdv;
  722. static double sum2 = 0;
  723. /* VARIABLES:
  724. atts = an array of the attributes; read from weight file.
  725. weight = weight from the weight file.
  726. edgeatts =
  727. edgemat =
  728. cntwhole = richness (total number of attributes)
  729. ln = sequence number, for the neighbor pixel, in the atts
  730. array
  731. lc = sequence number for an attribute in the richness
  732. array (NO LONGER USED)
  733. lr = sequence number, for the current pixel, in the atts
  734. array
  735. edge1 = sum of edges requested
  736. edge2 = sum of edges by type requested
  737. edge[0] = running total of juxtaposition values
  738. edge[1] = sum of edges
  739. edge[2] = st. dev. juxtaposition
  740. edge[3] = sum of edges by type
  741. */
  742. /* initialize variables */
  743. sum = cnt = 0;
  744. /* juxtaposition calc. step 1:
  745. each 4 line loop checks first
  746. that the pixel has non-null
  747. attribute, second finds the
  748. sequence number for the
  749. pixel's attribute in the
  750. attribute array, third sums
  751. the quantity and weight, and
  752. fourth sums the correct cnt */
  753. /* if this pixel has a non-null
  754. attribute, do the calculations */
  755. if ((buf[i0][j0] || buf[i0][j0] == 0) && null_buf[i0][j0] == 0.0) { /*1 */
  756. /* increment the count of non-zero
  757. pixels */
  758. total++;
  759. if (choice->jux[0])
  760. lr = find_loc(cntwhole, atts, buf[i0][j0]);
  761. /* if this pixel is not on the
  762. edge of the map in the first
  763. row, and if juxt. was chosen */
  764. if (i0 > 1 && choice->jux[0]) {
  765. /* neighbor 1: i0-1,j0 */
  766. if ((buf[i0 - 1][j0] || buf[i0 - 1][j0] == 0.0) &&
  767. null_buf[i0 - 1][j0] == 0.0) {
  768. ln = find_loc(cntwhole, atts, buf[i0 - 1][j0]);
  769. sum += 2 * weight[lr][ln];
  770. cnt += 2;
  771. }
  772. /* if this pixel is not on the
  773. edge of the map in the first
  774. col */
  775. if (j0 > 1) {
  776. /* neighbor 2: i0-1,j0-1 */
  777. if ((buf[i0 - 1][j0 - 1] || buf[i0 - 1][j0 - 1] == 0.0) &&
  778. null_buf[i0 - 1][j0 - 1] == 0.0) {
  779. ln = find_loc(cntwhole, atts, buf[i0 - 1][j0 - 1]);
  780. sum += weight[lr][ln];
  781. cnt++;
  782. }
  783. }
  784. /* if this pixel is not on the
  785. edge of the map in the last
  786. col */
  787. if (j0 < nc) {
  788. /* neighbor 3: i0-1,j0+1 */
  789. if ((buf[i0 - 1][j0 + 1] || buf[i0 - 1][j0 + 1] == 0.0) &&
  790. null_buf[i0 - 1][j0 + 1] == 0.0) {
  791. ln = find_loc(cntwhole, atts, buf[i0 - 1][j0 + 1]);
  792. sum += weight[lr][ln];
  793. cnt++;
  794. }
  795. }
  796. }
  797. /* if this pixel is not on the
  798. edge of the map in the last
  799. row and if juxta. was chosen */
  800. if (i0 < nr) {
  801. if (choice->jux[0]) {
  802. /* neighbor 4: i0+1,j0 */
  803. if ((buf[i0 + 1][j0] || buf[i0 + 1][j0] == 0.0) &&
  804. null_buf[i0 + 1][j0] == 0.0) {
  805. ln = find_loc(cntwhole, atts, buf[i0 + 1][j0]);
  806. sum += 2 * weight[lr][ln];
  807. cnt += 2;
  808. }
  809. /* if this pixel is not on the
  810. edge of the map in the first
  811. col */
  812. if (j0 > 1) {
  813. /* neighbor 5: i0+1,j0-1 */
  814. if ((buf[i0 + 1][j0 - 1] || buf[i0 + 1][j0 - 1] == 0.0) &&
  815. null_buf[i0 + 1][j0 - 1] == 0.0) {
  816. ln = find_loc(cntwhole, atts, buf[i0 + 1][j0 - 1]);
  817. sum += weight[lr][ln];
  818. cnt++;
  819. }
  820. }
  821. /* if this pixel is not on the
  822. edge of the map in the last
  823. col */
  824. if (j0 < nc) {
  825. /* neighbor 6: i0+1,j0+1 */
  826. if ((buf[i0 + 1][j0 + 1] || buf[i0 + 1][j0 + 1] == 0.0) &&
  827. null_buf[i0 + 1][j0 + 1] == 0.0) {
  828. ln = find_loc(cntwhole, atts, buf[i0 + 1][j0 + 1]);
  829. sum += weight[lr][ln];
  830. cnt++;
  831. }
  832. }
  833. }
  834. /* if the i0+1, j0 pixel is different,
  835. and both pixels have non-null
  836. attributes */
  837. if (choice->edg[0] && (buf[i0][j0] != buf[i0 + 1][j0]) &&
  838. (buf[i0 + 1][j0] || buf[i0 + 1][j0] == 0.0) &&
  839. null_buf[i0 + 1][j0] == 0.0) {
  840. /* then increment edge[1] to
  841. indicate that an edge has been
  842. found if sum of edges requested */
  843. if (choice->edg[1])
  844. edge[1]++;
  845. /* then increment edge[2] to
  846. indicate that an edge has been
  847. found if the edge is one of the
  848. types requested and if sum of
  849. edges by type requested */
  850. if (choice->edg[2]) {
  851. fr = find_edge(cntwhole, edgeatts, buf[i0][j0]);
  852. to = find_edge(cntwhole, edgeatts, buf[i0 + 1][j0]);
  853. if (edgemat[fr][to]) {
  854. edge[3]++;
  855. if (choice->edgemap)
  856. *edge1 = 1;
  857. }
  858. }
  859. }
  860. }
  861. /* regardless which row this pixel
  862. is in (even if edge row); if
  863. this pixel is not on the edge
  864. of the map in the first col, and
  865. if juxta. was chosen */
  866. if (j0 > 1 && choice->jux[0]) {
  867. /* neighbor 7: i0,j0-1 */
  868. if ((buf[i0][j0 - 1] || buf[i0][j0 - 1] == 0.0) &&
  869. null_buf[i0][j0 - 1] == 0.0) {
  870. ln = find_loc(cntwhole, atts, buf[i0][j0 - 1]);
  871. sum += 2 * weight[lr][ln];
  872. cnt += 2;
  873. }
  874. }
  875. /* regardless which row this pixel
  876. is in (even if edge row); if
  877. this pixel is not on the edge
  878. of the map in the last col, and
  879. if juxta. was chosen */
  880. if (j0 < nc) {
  881. if (choice->jux[0]) {
  882. /* neighbor 8: i0,j0+1 */
  883. if ((buf[i0][j0 + 1] || buf[i0][j0 + 1] == 0.0) &&
  884. null_buf[i0][j0 + 1] == 0.0) {
  885. ln = find_loc(cntwhole, atts, buf[i0][j0 + 1]);
  886. sum += 2 * weight[lr][ln];
  887. cnt += 2;
  888. }
  889. }
  890. /* if the i0, j0+1 pixel is different,
  891. and both pixels have non-zero
  892. attributes */
  893. if (choice->edg[0] && (buf[i0][j0] != buf[i0][j0 + 1]) &&
  894. (buf[i0][j0 + 1] || buf[i0][j0 + 1] == 0.0) &&
  895. null_buf[i0][j0 + 1] == 0.0) {
  896. /* then increment edge[1] to
  897. indicate that an edge has been
  898. found if sum of edges requested */
  899. if (choice->edg[1])
  900. edge[1]++;
  901. /* then increment edge[2] to
  902. indicate that an edge has been
  903. found if the edge is one of the
  904. types requested and if sum of
  905. edges by type requested */
  906. if (choice->edg[2]) {
  907. fr = find_edge(cntwhole, edgeatts, buf[i0][j0]);
  908. to = find_edge(cntwhole, edgeatts, buf[i0][j0 + 1]);
  909. if (edgemat[fr][to]) {
  910. edge[3]++;
  911. if (choice->edgemap)
  912. *edge2 = 1;
  913. }
  914. }
  915. }
  916. }
  917. }
  918. /* calculate juxtaposition and
  919. add it to the running total
  920. in edge[0] */
  921. if (choice->jux[0]) {
  922. if (cnt)
  923. juxta = sum / cnt;
  924. else
  925. juxta = 0.0;
  926. edge[0] += juxta;
  927. sum2 += juxta * juxta;
  928. }
  929. /* if this is the last pixel in
  930. the sampling area and juxta-
  931. position was chosen */
  932. if (choice->jux[0] && i0 == nr && j0 == nc) {
  933. edge[0] /= total;
  934. stdv = (double)sum2 / total - edge[0] * edge[0];
  935. if (stdv > 0)
  936. edge[2] = sqrt(stdv);
  937. sum2 = 0;
  938. }
  939. return;
  940. }
  941. /* READ THE WEIGHT FILE */
  942. void read_weight(int richcount, double atts[], double **weight, int *attcnt)
  943. {
  944. FILE *fp;
  945. register int i, j;
  946. float tmp;
  947. /* open the weight file */
  948. fp = fopen2("r.le.para/weight", "r");
  949. /* read the attributes into
  950. the atts array */
  951. for (i = 0; i < richcount; i++) {
  952. fscanf(fp, "%f", &tmp);
  953. atts[i] = tmp;
  954. }
  955. while (fgetc(fp) != '\n')
  956. if (fgetc(fp) != ' ') {
  957. fprintf(stdout, "\n");
  958. fprintf(stdout,
  959. " *************************************************\n");
  960. fprintf(stdout,
  961. " The weight file (r.le.para/weight) is incorrect \n");
  962. fprintf(stdout,
  963. " since more/less than the %d attributes found \n",
  964. richcount);
  965. fprintf(stdout,
  966. " in the map are listed in the weight file \n");
  967. fprintf(stdout,
  968. " *************************************************\n");
  969. exit(1);
  970. }
  971. /* read the weights, skipping
  972. the first column, which
  973. contains the attribute again */
  974. for (i = 0; i < richcount; i++) {
  975. fscanf(fp, "%f", &tmp);
  976. for (j = 0; j < i; j++) {
  977. weight[i][j] = weight[j][i];
  978. }
  979. for (j = 0; j < richcount; j++) {
  980. fscanf(fp, "%f", &tmp);
  981. weight[i][j] = tmp;
  982. }
  983. while (fgetc(fp) != '\n') ;
  984. }
  985. fclose(fp);
  986. return;
  987. }
  988. /* READ THE EDGE FILE */
  989. void read_edge(int richcount, double atts[], double **edge)
  990. {
  991. FILE *fp;
  992. register int i, j;
  993. float tmp;
  994. /* open the edge file */
  995. fp = fopen3("r.le.para/edge", "r");
  996. /* read the attributes into
  997. the atts array */
  998. for (i = 0; i < richcount; i++) {
  999. fscanf(fp, "%f", &tmp);
  1000. atts[i] = tmp;
  1001. }
  1002. while (fgetc(fp) != '\n')
  1003. if (fgetc(fp) != ' ') {
  1004. fprintf(stdout, "\n");
  1005. fprintf(stdout,
  1006. " *************************************************\n");
  1007. fprintf(stdout,
  1008. " The edge file (r.le.para/edge) is incorrect \n");
  1009. fprintf(stdout,
  1010. " since more/less than the %d attributes found \n",
  1011. richcount);
  1012. fprintf(stdout,
  1013. " in the map are listed in the edge file \n");
  1014. fprintf(stdout,
  1015. " *************************************************\n");
  1016. exit(1);
  1017. }
  1018. /* read the edge weights, skipping
  1019. the first column, which
  1020. contains the attribute again */
  1021. for (i = 0; i < richcount; i++) {
  1022. fscanf(fp, "%f", &tmp);
  1023. for (j = 0; j < i; j++) {
  1024. edge[i][j] = edge[j][i];
  1025. }
  1026. for (j = 0; j < richcount; j++) {
  1027. fscanf(fp, "%f", &tmp);
  1028. edge[i][j] = tmp;
  1029. }
  1030. while (fgetc(fp) != '\n') ;
  1031. }
  1032. fclose(fp);
  1033. return;
  1034. }
  1035. /* FIND THE SEQUENCE NUMBER FOR
  1036. AN ATTRIBUTE IN THE ATTRIBUTE
  1037. ARRAY WHICH IS READ FROM THE
  1038. WEIGHT FILE */
  1039. int find_loc(int richcount, double atts[], double test)
  1040. {
  1041. register int i;
  1042. G_sleep_on_error(0);
  1043. for (i = 0; i < richcount; i++) {
  1044. if (test == atts[i])
  1045. return i;
  1046. }
  1047. G_fatal_error("The weight file in r.le.para is incorrect, exit\n");
  1048. return (0);
  1049. }
  1050. /* FIND THE SEQUENCE NUMBER FOR
  1051. AN ATTRIBUTE IN THE ATTRIBUTE
  1052. ARRAY WHICH IS READ FROM THE
  1053. EDGE FILE */
  1054. int find_edge(int richcount, double atts[], double test)
  1055. {
  1056. register int i;
  1057. G_sleep_on_error(0);
  1058. for (i = 0; i < richcount; i++) {
  1059. if (test == atts[i]) {
  1060. return i;
  1061. }
  1062. }
  1063. G_fatal_error("The edge file in r.le.para is incorrect, exit\n");
  1064. return (0);
  1065. }
  1066. /* FIND THE SEQUENCE NO. OF AN
  1067. ATTRIBUTE IN THE RICHNESS ARRAY */
  1068. int check_order(double att, double *rich)
  1069. {
  1070. int i = 0;
  1071. while (att != rich[i])
  1072. i++;
  1073. return i;
  1074. }