cellclip.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. /*
  2. ************************************************************
  3. * MODULE: r.le.pixel/cellclip.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. * cellclip.c clips the area that is being analyzed *
  11. * out of the original raster map *
  12. * *
  13. * COPYRIGHT: (C) 2001 by W.L. Baker *
  14. * *
  15. * This program is free software under the GNU General *
  16. * Public License(>=v2). Read the file COPYING that comes *
  17. * with GRASS for details *
  18. * *
  19. ************************************************************/
  20. #include <grass/gis.h>
  21. #include "pixel.h"
  22. #include <grass/config.h>
  23. #include <grass/raster.h>
  24. #include "local_proto.h"
  25. extern struct CHOICE *choice;
  26. extern int finput;
  27. /* CELL CLIP DRIVER */
  28. void cell_clip_drv(int col0, int row0, int ncols, int nrows, double **value,
  29. int index, int cntwhole, float radius)
  30. {
  31. register int i, j;
  32. int cnt = 0, p;
  33. double *rich, *richtmp;
  34. char *name, *mapset;
  35. DCELL **buf;
  36. DCELL **null_buf;
  37. RASTER_MAP_TYPE data_type;
  38. /*
  39. col0 = starting column for area to be clipped
  40. row0 = starting row for area to be clipped
  41. ncols = number of columns in area to be clipped
  42. nrows = number of rows in area to be clipped
  43. value =
  44. index = number of the region to be clipped, if there's a region map
  45. buf = pointer to array containing the clipped area, a smaller area
  46. than the original raster map to be read from finput printf("h2\n");
  47. pat = pointer to array containing the map of patch numbers
  48. cor = pointer to array containing the map of interior area
  49. */
  50. name = choice->fn;
  51. mapset = G_mapset();
  52. data_type = Rast_map_type(name, mapset);
  53. /* dynamically allocate storage for the
  54. buffer that will hold the contents of
  55. the window */
  56. buf = (DCELL **) G_calloc(nrows + 3, sizeof(DCELL *));
  57. for (i = 0; i < nrows + 3; i++) {
  58. buf[i] = (DCELL *) G_calloc(ncols + 3, sizeof(DCELL));
  59. }
  60. /* dynamically allocate storage for the
  61. buffer that will hold the null values for
  62. the clipped area */
  63. null_buf = (DCELL **) G_calloc(nrows + 3, sizeof(DCELL *));
  64. for (i = 0; i < nrows + 3; i++)
  65. null_buf[i] = (DCELL *) G_calloc(ncols + 3, sizeof(DCELL));
  66. /* call the cell_clip routine */
  67. cell_clip(buf, null_buf, row0, col0, nrows, ncols, index, radius);
  68. /* dynamically allocate memory for
  69. the richness array */
  70. richtmp = (double *)G_calloc(MAX, sizeof(double));
  71. /* go through the sampling area
  72. pixel by pixel */
  73. for (i = 1; i < nrows + 1; i++) {
  74. for (j = 1; j < ncols + 1; j++) {
  75. /* if buf[i][j] is not a null value,
  76. call get_rich to tally up the
  77. number of different attributes
  78. in the sampling area and fill
  79. the richness array with those
  80. attributes */
  81. if ((buf[i][j] || buf[i][j] == 0.0) && null_buf[i][j] == 0.0) {
  82. /*printf("buf[%d][%d] = %f\n",i,j,buf[i][j]); */
  83. get_rich(buf[i][j], richtmp, &cnt);
  84. }
  85. }
  86. }
  87. if (cnt) {
  88. rich = (double *)G_calloc(cnt, sizeof(double));
  89. for (i = 0; i < cnt; i++) {
  90. rich[i] = richtmp[i];
  91. }
  92. G_free(richtmp);
  93. /* call ANSI C runtime library
  94. function qsort to sort the
  95. richness array into ascending
  96. order */
  97. qsort(rich, cnt, sizeof(double), compar);
  98. /* moving window */
  99. if (choice->wrum == 'm') {
  100. if (is_not_empty_buffer(buf, null_buf, nrows + 1, ncols + 1)) {
  101. if (center_is_not_null(buf, null_buf, nrows, ncols))
  102. mv_texture(nrows, ncols, buf, null_buf, value, index,
  103. rich, cnt, cntwhole);
  104. else {
  105. for (p = 0; p < 17; p++)
  106. *(*(value + index) + p) = -BIG;
  107. }
  108. }
  109. }
  110. /* whole map, units, or regions */
  111. else if (is_not_empty_buffer(buf, null_buf, nrows + 1, ncols + 1))
  112. df_texture(nrows, ncols, buf, null_buf, rich, cnt, cntwhole);
  113. for (i = 0; i < nrows + 3; i++)
  114. G_free(*(buf + i));
  115. G_free(buf);
  116. /* free memory allocated for null buffer */
  117. for (i = 0; i < nrows + 3; i++)
  118. G_free(null_buf[i]);
  119. G_free(null_buf);
  120. G_free(rich);
  121. }
  122. else
  123. G_free(richtmp);
  124. return;
  125. }
  126. /* CHECK BUFFER; RETURN 1 IF BUFFER
  127. IS NOT EMPTY, 0 IF EMPTY */
  128. int is_not_empty_buffer(DCELL ** buf, DCELL ** null_buf, int rows, int cols)
  129. {
  130. register int i, j;
  131. /* if value in raster is positive or
  132. negative, then it is not null; if
  133. value in raster is zero, and the
  134. null value is 0.0, then the zero
  135. raster value is not null */
  136. for (i = 1; i < rows + 1; i++)
  137. for (j = 1; j < cols + 1; j++) {
  138. if (buf[i][j])
  139. return (1);
  140. else if (!buf[i][j] && null_buf[i][j] == 0.0)
  141. return (1);
  142. }
  143. return (0);
  144. }
  145. /* CHECK TO SEE IF THE CENTER PIXEL
  146. IN THE BUFFER IS NULL. RETURN 1
  147. IF IT IS NOT NULL, 0 IF IT IS NULL */
  148. int center_is_not_null(DCELL ** buf, DCELL ** null_buf, int rows, int cols)
  149. {
  150. /* if value in raster is positive or
  151. negative, then it is not null; if
  152. value in raster is zero, and the
  153. null value is 0.0, then the zero
  154. raster value is not null */
  155. if (buf[(rows / 2) + 1][(cols / 2) + 1] > -BIG) {
  156. return (1);
  157. }
  158. else if (!buf[(rows / 2) + 1][(cols / 2) + 1] &&
  159. null_buf[(rows / 2) + 1][(cols / 2) + 1] == 0.0) {
  160. return (1);
  161. }
  162. return (0);
  163. }
  164. /* OPEN THE RASTER FILE TO BE CLIPPED,
  165. AND DO THE CLIPPING */
  166. void cell_clip(DCELL ** buf, DCELL ** null_buf, int row0, int col0, int nrows,
  167. int ncols, int index, float radius)
  168. {
  169. CELL *tmp, *tmp1;
  170. FCELL *ftmp;
  171. DCELL *dtmp;
  172. char *tmpname, *nulltmp;
  173. int fr;
  174. register int i, j;
  175. double center_row = 0.0, center_col = 0.0;
  176. double dist;
  177. RASTER_MAP_TYPE data_type;
  178. /*
  179. Variables:
  180. IN:
  181. buf = pointer to array containing only the pixels inside the area
  182. that was specified to be clipped, so a smaller array than the
  183. original raster map
  184. null_buf = pointer to array containing the corresponding null values
  185. row0 = starting row for the area to be clipped out of the raster map
  186. col0 = starting col for the area to be clipped out of the raster map
  187. nrows = total number of rows in the area to be clipped
  188. ncols = total number of cols in the area to be clipped
  189. index = number of the region to be clipped, if there's a region map
  190. INTERNAL:
  191. tmp = pointer to a temporary array to store a row of the raster map
  192. tmp1 = pointer to a temporary array to store a row of the region map
  193. fr = return value from attempting to open the region map
  194. i, j = indices to rows and cols of the arrays
  195. */
  196. data_type = Rast_map_type(choice->fn, G_mapset());
  197. /* if sampling by region was chosen, check
  198. for the region map and make sure it is
  199. an integer (CELL_TYPE) map */
  200. if (choice->wrum == 'r') {
  201. if (0 > (fr = Rast_open_old(choice->reg, G_mapset()))) {
  202. fprintf(stderr, "\n");
  203. fprintf(stderr,
  204. " *******************************************************\n");
  205. fprintf(stderr,
  206. " You specified sam=r to request sampling by region, \n");
  207. fprintf(stderr,
  208. " but the region map specified with the 'reg=' parameter\n");
  209. fprintf(stderr,
  210. " cannot be found in the current mapset. \n");
  211. fprintf(stderr,
  212. " *******************************************************\n");
  213. exit(1);
  214. }
  215. if (Rast_map_type(choice->reg, G_mapset()) > 0) {
  216. fprintf(stderr, "\n");
  217. fprintf(stderr,
  218. " *******************************************************\n");
  219. fprintf(stderr,
  220. " You specified sam=r to request sampling by region, \n");
  221. fprintf(stderr,
  222. " but the region map specified with the 'reg=' parameter\n");
  223. fprintf(stderr,
  224. " must be an integer map, and it is floating point or \n");
  225. fprintf(stderr,
  226. " double instead. \n");
  227. fprintf(stderr,
  228. " *******************************************************\n");
  229. exit(1);
  230. }
  231. tmp1 = Rast_allocate_buf(CELL_TYPE);
  232. Rast_zero_buf(tmp1, CELL_TYPE);
  233. fprintf(stderr, "Analyzing region number %d...\n", index);
  234. }
  235. /* allocate memory to store a row of the
  236. raster map, depending on the type of
  237. input raster map; keep track of the
  238. name of the buffer for each raster type */
  239. switch (data_type) {
  240. case CELL_TYPE:
  241. tmp = Rast_allocate_buf(CELL_TYPE);
  242. tmpname = "tmp";
  243. break;
  244. case FCELL_TYPE:
  245. ftmp = Rast_allocate_buf(FCELL_TYPE);
  246. tmpname = "ftmp";
  247. break;
  248. case DCELL_TYPE:
  249. dtmp = Rast_allocate_buf(DCELL_TYPE);
  250. tmpname = "dtmp";
  251. break;
  252. }
  253. /* allocate memory to store a row of the
  254. null values corresponding to the raster
  255. map */
  256. nulltmp = Rast_allocate_null_buf();
  257. /* if circles are used for sampling, then
  258. calculate the center of the area to be
  259. clipped, in pixels */
  260. if ((int)radius) {
  261. center_row = ((double)row0 + ((double)nrows - 1) / 2);
  262. center_col = ((double)col0 + ((double)ncols - 1) / 2);
  263. }
  264. /* for each row of the area to be clipped */
  265. for (i = row0; i < row0 + nrows; i++) {
  266. /* if region, read in the corresponding
  267. map row in the region file */
  268. if (choice->wrum == 'r')
  269. Rast_get_row_nomask(fr, tmp1, i, CELL_TYPE);
  270. /* initialize each element of the
  271. row buffer to 0; this row buffer
  272. will hold one row of the clipped
  273. raster map. Then read row i of the
  274. map and the corresponding null values
  275. into tmp and nulltmp buffers */
  276. switch (data_type) {
  277. case CELL_TYPE:
  278. Rast_zero_buf(tmp, data_type);
  279. Rast_get_row(finput, tmp, i, CELL_TYPE);
  280. break;
  281. case FCELL_TYPE:
  282. Rast_zero_buf(ftmp, data_type);
  283. Rast_get_row(finput, ftmp, i, FCELL_TYPE);
  284. break;
  285. case DCELL_TYPE:
  286. Rast_zero_buf(dtmp, data_type);
  287. Rast_get_row(finput, dtmp, i, DCELL_TYPE);
  288. break;
  289. }
  290. Rast_get_null_value_row(finput, nulltmp, i);
  291. /* for all the columns one by one */
  292. for (j = col0; j < col0 + ncols; j++) {
  293. /* if circles are used for sampling */
  294. if ((int)radius) {
  295. dist = sqrt(((double)i - center_row) *
  296. ((double)i - center_row) +
  297. ((double)j - center_col) *
  298. ((double)j - center_col));
  299. /* copy the contents of tmp into the
  300. appropriate cell in buf */
  301. if (dist < radius) {
  302. switch (data_type) {
  303. case CELL_TYPE:
  304. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(tmp + j);
  305. break;
  306. case FCELL_TYPE:
  307. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(ftmp + j);
  308. break;
  309. case DCELL_TYPE:
  310. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(dtmp + j);
  311. break;
  312. }
  313. *(*(null_buf + i + 1 - row0) + j + 1 - col0) =
  314. *(nulltmp + j);
  315. }
  316. }
  317. /* if circles are not used and
  318. if the choice is not "by region" or
  319. if this column is in region "index" */
  320. else if (choice->wrum != 'r' || *(tmp1 + j) == index) {
  321. /* copy the contents of the correct tmp
  322. into the appropriate cell in the buf
  323. and the corresponding null values into
  324. the appropriate cell in null_buf */
  325. switch (data_type) {
  326. case CELL_TYPE:
  327. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(tmp + j);
  328. break;
  329. case FCELL_TYPE:
  330. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(ftmp + j);
  331. break;
  332. case DCELL_TYPE:
  333. *(*(buf + i + 1 - row0) + j + 1 - col0) = *(dtmp + j);
  334. break;
  335. }
  336. *(*(null_buf + i + 1 - row0) + j + 1 - col0) = *(nulltmp + j);
  337. }
  338. }
  339. }
  340. switch (data_type) {
  341. case CELL_TYPE:
  342. G_free(tmp);
  343. break;
  344. case FCELL_TYPE:
  345. G_free(ftmp);
  346. break;
  347. case DCELL_TYPE:
  348. G_free(dtmp);
  349. break;
  350. }
  351. if (choice->wrum == 'r') {
  352. G_free(tmp1);
  353. Rast_close(fr);
  354. }
  355. G_free(nulltmp);
  356. return;
  357. }
  358. /* FIND UNCOUNTED ATTRIBUTES,
  359. COUNT THEM UP, AND ADD THEM TO
  360. THE RICHNESS ARRAY IN UNSORTED
  361. ORDER */
  362. void get_rich(double att, double rich[], int *cnt)
  363. {
  364. register int i;
  365. /* if this attribute is already
  366. in the richness array, then
  367. return */
  368. for (i = 0; i < *cnt; i++) {
  369. if (att == rich[i]) {
  370. break;
  371. }
  372. }
  373. /* if this attribute is not already
  374. in the richness array, then make
  375. it the "cnt" element of the
  376. array, then increment the cnt */
  377. if (i >= *cnt) {
  378. rich[*cnt] = att;
  379. /* fprintf(stderr, "cnt=%d i=%d att=%f\n",*cnt,i,att); */
  380. ++(*cnt);
  381. }
  382. return;
  383. }
  384. /* COMPARE */
  385. int compar(int *i, int *j)
  386. {
  387. return (*i - *j);
  388. }