iscatt_core.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004
  1. /*!
  2. \file lib/imagery/iscatt_core.c
  3. \brief Imagery library - wx.iscatt (wx Interactive Scatter Plot Tool) backend.
  4. Copyright (C) 2013 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Stepan Turek <stepan.turek@seznam.cz> (GSoC 2013, Mentor: Martin Landa)
  8. */
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <grass/gis.h>
  13. #include <grass/vector.h>
  14. #include <grass/raster.h>
  15. #include <grass/imagery.h>
  16. #include <grass/glocale.h>
  17. #include "iclass_local_proto.h"
  18. struct rast_row
  19. {
  20. CELL *row;
  21. char *null_row;
  22. struct Range rast_range; /*Range of whole raster. */
  23. };
  24. /*!
  25. \brief Create pgm header.
  26. Scatter plot internally generates pgm files.
  27. These pgms have header in format created by this function.
  28. \param region region to be pgm header generated for
  29. \param [out] header header of pgm file
  30. */
  31. static int get_cat_rast_header(struct Cell_head *region, char *header)
  32. {
  33. return sprintf(header, "P5\n%d\n%d\n1\n", region->cols, region->rows);
  34. }
  35. /*!
  36. \brief Create category raster conditions file.
  37. The file is used for holding selected areas from mapwindow.
  38. The reason why the standard GRASS raster is not used is that for every
  39. modification (new area is selected) we would need to create whole new raster.
  40. Instead of this scatter plot only modifies affected region in
  41. the internal pgm file.
  42. \param cat_rast_region region to be file generated for
  43. \param[out] cat_rast path where the pgm raster file will be generated
  44. */
  45. int I_create_cat_rast(struct Cell_head *cat_rast_region, const char *cat_rast)
  46. {
  47. FILE *f_cat_rast;
  48. char cat_rast_header[1024]; /* TODO magic number */
  49. int i_row, i_col;
  50. int head_nchars;
  51. unsigned char *row_data;
  52. f_cat_rast = fopen(cat_rast, "wb");
  53. if (!f_cat_rast) {
  54. G_warning("Unable to create category raster condition file <%s>.",
  55. cat_rast);
  56. return -1;
  57. }
  58. head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
  59. fwrite(cat_rast_header, sizeof(char), head_nchars / sizeof(char),
  60. f_cat_rast);
  61. if (ferror(f_cat_rast)) {
  62. fclose(f_cat_rast);
  63. G_warning(_
  64. ("Unable to write header into category raster condition file <%s>."),
  65. cat_rast);
  66. return -1;
  67. }
  68. row_data =
  69. (unsigned char *)G_malloc(cat_rast_region->cols *
  70. sizeof(unsigned char));
  71. for (i_col = 0; i_col < cat_rast_region->cols; i_col++)
  72. row_data[i_col] = 0 & 255;
  73. for (i_row = 0; i_row < cat_rast_region->rows; i_row++) {
  74. fwrite(row_data, sizeof(unsigned char),
  75. (cat_rast_region->cols) / sizeof(unsigned char), f_cat_rast);
  76. if (ferror(f_cat_rast)) {
  77. fclose(f_cat_rast);
  78. G_warning(_
  79. ("Unable to write into category raster condition file <%s>."),
  80. cat_rast);
  81. return -1;
  82. }
  83. }
  84. fclose(f_cat_rast);
  85. return 0;
  86. }
  87. /*!
  88. \brief Find intersection region of two regions.
  89. \param A pointer to intersected region
  90. \param B pointer to intersected region
  91. \param [out] intersec pointer to intersection region of regions A B
  92. (relevant params of the region are: south, north, east, west)
  93. \return 0 if interection exists
  94. \return -1 if regions does not intersect
  95. */
  96. static int regions_intersecion(struct Cell_head *A, struct Cell_head *B,
  97. struct Cell_head *intersec)
  98. {
  99. if (B->north < A->south)
  100. return -1;
  101. else if (B->north > A->north)
  102. intersec->north = A->north;
  103. else
  104. intersec->north = B->north;
  105. if (B->south > A->north)
  106. return -1;
  107. else if (B->south < A->south)
  108. intersec->south = A->south;
  109. else
  110. intersec->south = B->south;
  111. if (B->east < A->west)
  112. return -1;
  113. else if (B->east > A->east)
  114. intersec->east = A->east;
  115. else
  116. intersec->east = B->east;
  117. if (B->west > A->east)
  118. return -1;
  119. else if (B->west < A->west)
  120. intersec->west = A->west;
  121. else
  122. intersec->west = B->west;
  123. if (intersec->north == intersec->south)
  124. return -1;
  125. if (intersec->east == intersec->west)
  126. return -1;
  127. return 0;
  128. }
  129. /*!
  130. \brief Get rows and cols numbers, which defines intersection of the regions.
  131. \param A pointer to intersected region
  132. \param B pointer to intersected region (A and B must have same resolution)
  133. \param [out] A_bounds rows and cols numbers of A stored in
  134. south, north, east, west, which defines intersection of A and B
  135. \param [out] B_bounds rows and cols numbers of B stored in
  136. south, north, east, west, which defines intersection of A and B
  137. \return 0 if interection exists
  138. \return -1 if regions do not intersect
  139. \return -2 resolution of regions is not same
  140. */
  141. static int get_rows_and_cols_bounds(struct Cell_head *A, struct Cell_head *B,
  142. struct Cell_head *A_bounds,
  143. struct Cell_head *B_bounds)
  144. {
  145. float ns_res, ew_res;
  146. struct Cell_head intersec;
  147. /* TODO is it right check? */
  148. if (abs(A->ns_res - B->ns_res) > GRASS_EPSILON) {
  149. G_warning(
  150. "'get_rows_and_cols_bounds' ns_res does not fit, A->ns_res: %f B->ns_res: %f",
  151. A->ns_res, B->ns_res);
  152. return -2;
  153. }
  154. if (abs(A->ew_res - B->ew_res) > GRASS_EPSILON) {
  155. G_warning(
  156. "'get_rows_and_cols_bounds' ew_res does not fit, A->ew_res: %f B->ew_res: %f",
  157. A->ew_res, B->ew_res);
  158. return -2;
  159. }
  160. ns_res = A->ns_res;
  161. ew_res = A->ew_res;
  162. if (regions_intersecion(A, B, &intersec) == -1)
  163. return -1;
  164. A_bounds->north =
  165. ceil((A->north - intersec.north - ns_res * 0.5) / ns_res);
  166. A_bounds->south =
  167. ceil((A->north - intersec.south - ns_res * 0.5) / ns_res);
  168. A_bounds->east = ceil((intersec.east - A->west - ew_res * 0.5) / ew_res);
  169. A_bounds->west = ceil((intersec.west - A->west - ew_res * 0.5) / ew_res);
  170. B_bounds->north =
  171. ceil((B->north - intersec.north - ns_res * 0.5) / ns_res);
  172. B_bounds->south =
  173. ceil((B->north - intersec.south - ns_res * 0.5) / ns_res);
  174. B_bounds->east = ceil((intersec.east - B->west - ew_res * 0.5) / ew_res);
  175. B_bounds->west = ceil((intersec.west - B->west - ew_res * 0.5) / ew_res);
  176. return 0;
  177. }
  178. /*!
  179. \brief Insert raster map patch into pgm file.
  180. \see I_create_cat_rast
  181. Warning: calls Rast_set_window
  182. \param patch_rast name of raster map
  183. \param cat_rast_region region of category raster file
  184. \param cat_rast path to category raster file
  185. \return 0 on success
  186. \return -1 on failure
  187. */
  188. int I_insert_patch_to_cat_rast(const char *patch_rast,
  189. struct Cell_head *cat_rast_region,
  190. const char *cat_rast)
  191. {
  192. FILE *f_cat_rast;
  193. struct Cell_head patch_region, patch_bounds, cat_rast_bounds;
  194. char cat_rast_header[1024];
  195. int i_row, i_col, ncols, nrows, patch_col;
  196. int head_nchars, ret;
  197. int fd_patch_rast, init_shift, step_shift;
  198. unsigned char *patch_data;
  199. char *null_chunk_row;
  200. const char *mapset;
  201. f_cat_rast = fopen(cat_rast, "rb+");
  202. if (!f_cat_rast) {
  203. G_warning(_("Unable to open category raster condtions file <%s>."),
  204. cat_rast);
  205. return -1;
  206. }
  207. head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
  208. if ((mapset = G_find_raster((char *)patch_rast, "")) == NULL) {
  209. fclose(f_cat_rast);
  210. G_warning(_("Unable to find patch raster <%s>."), patch_rast);
  211. return -1;
  212. }
  213. Rast_get_cellhd(patch_rast, mapset, &patch_region);
  214. Rast_set_window(&patch_region);
  215. if ((fd_patch_rast = Rast_open_old(patch_rast, mapset)) < 0) {
  216. fclose(f_cat_rast);
  217. return -1;
  218. }
  219. ret =
  220. get_rows_and_cols_bounds(cat_rast_region, &patch_region,
  221. &cat_rast_bounds, &patch_bounds);
  222. if (ret == -2) {
  223. G_warning(_
  224. ("Resolutions of patch <%s> and patched file <%s> are not same."),
  225. patch_rast, cat_rast);
  226. Rast_close(fd_patch_rast);
  227. fclose(f_cat_rast);
  228. return -1;
  229. }
  230. else if (ret == -1) {
  231. Rast_close(fd_patch_rast);
  232. fclose(f_cat_rast);
  233. return 0;
  234. }
  235. ncols = cat_rast_bounds.east - cat_rast_bounds.west;
  236. nrows = cat_rast_bounds.south - cat_rast_bounds.north;
  237. patch_data = (unsigned char *)G_malloc(ncols * sizeof(unsigned char));
  238. init_shift =
  239. head_nchars + cat_rast_region->cols * cat_rast_bounds.north +
  240. cat_rast_bounds.west;
  241. if (fseek(f_cat_rast, init_shift, SEEK_SET) != 0) {
  242. G_warning(_
  243. ("Corrupted category raster conditions file <%s> (fseek failed)"),
  244. cat_rast);
  245. Rast_close(fd_patch_rast);
  246. fclose(f_cat_rast);
  247. return -1;
  248. }
  249. step_shift = cat_rast_region->cols - ncols;
  250. null_chunk_row = Rast_allocate_null_buf();
  251. for (i_row = 0; i_row < nrows; i_row++) {
  252. Rast_get_null_value_row(fd_patch_rast, null_chunk_row,
  253. i_row + patch_bounds.north);
  254. for (i_col = 0; i_col < ncols; i_col++) {
  255. patch_col = patch_bounds.west + i_col;
  256. if (null_chunk_row[patch_col] != 1)
  257. patch_data[i_col] = 1 & 255;
  258. else {
  259. patch_data[i_col] = 0 & 255;
  260. }
  261. }
  262. fwrite(patch_data, sizeof(unsigned char),
  263. (ncols) / sizeof(unsigned char), f_cat_rast);
  264. if (ferror(f_cat_rast)) {
  265. G_warning(_
  266. ("Unable to write into category raster conditions file <%s>"),
  267. cat_rast);
  268. Rast_close(fd_patch_rast);
  269. G_free(null_chunk_row);
  270. fclose(f_cat_rast);
  271. return -1;
  272. }
  273. if (fseek(f_cat_rast, step_shift, SEEK_CUR) != 0) {
  274. G_warning(_
  275. ("Corrupted category raster conditions file <%s> (fseek failed)"),
  276. cat_rast);
  277. Rast_close(fd_patch_rast);
  278. G_free(null_chunk_row);
  279. fclose(f_cat_rast);
  280. return -1;
  281. }
  282. }
  283. Rast_close(fd_patch_rast);
  284. G_free(null_chunk_row);
  285. fclose(f_cat_rast);
  286. return 0;
  287. }
  288. /*!
  289. \brief Updates scatter plots data in category by pixels which meets category conditions.
  290. \param bands_rows data represents data describig one row from raster band
  291. \param belongs_pix array which defines which pixels belongs to category
  292. (1 value) and which not (0 value)
  293. \param [out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
  294. which are modified according to values in belongs_pix
  295. (represents scatter plot category)
  296. */
  297. static void update_cat_scatt_plts(struct rast_row *bands_rows,
  298. unsigned short *belongs_pix,
  299. struct scScatts *scatts)
  300. {
  301. int i_scatt, array_idx, i_chunk_rows_pix, max_arr_idx;
  302. CELL *b_1_row;
  303. CELL *b_2_row;
  304. char *b_1_null_row, *b_2_null_row;
  305. struct rast_row b_1_rast_row, b_2_rast_row;
  306. struct Range b_1_range, b_2_range;
  307. int b_1_range_size;
  308. int row_size = Rast_window_cols();
  309. int *scatts_bands = scatts->scatts_bands;
  310. for (i_scatt = 0; i_scatt < scatts->n_a_scatts; i_scatt++) {
  311. b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
  312. b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
  313. b_1_row = b_1_rast_row.row;
  314. b_2_row = b_2_rast_row.row;
  315. b_1_null_row = b_1_rast_row.null_row;
  316. b_2_null_row = b_2_rast_row.null_row;
  317. b_1_range = b_1_rast_row.rast_range;
  318. b_2_range = b_2_rast_row.rast_range;
  319. b_1_range_size = b_1_range.max - b_1_range.min + 1;
  320. max_arr_idx =
  321. (b_1_range.max - b_1_range.min + 1) * (b_2_range.max -
  322. b_2_range.min + 1);
  323. for (i_chunk_rows_pix = 0; i_chunk_rows_pix < row_size;
  324. i_chunk_rows_pix++) {
  325. /* pixel does not belongs to scatter plot or has null value in one of the bands */
  326. if (!belongs_pix[i_chunk_rows_pix] ||
  327. b_1_null_row[i_chunk_rows_pix] == 1 ||
  328. b_2_null_row[i_chunk_rows_pix] == 1)
  329. continue;
  330. /* index in scatter plot array */
  331. array_idx =
  332. b_1_row[i_chunk_rows_pix] - b_1_range.min +
  333. (b_2_row[i_chunk_rows_pix] - b_2_range.min) * b_1_range_size;
  334. if (array_idx < 0 || array_idx >= max_arr_idx) {
  335. G_warning
  336. ("Inconsistent data. Value computed for scatter plot is out of initialized range.");
  337. continue;
  338. }
  339. /* increment scatter plot value */
  340. ++scatts->scatts_arr[i_scatt]->scatt_vals_arr[array_idx];
  341. }
  342. }
  343. }
  344. /*!
  345. \brief Computes scatter plots data from bands_rows.
  346. \param scatt_conds pointer to scScatts struct of type SC_SCATT_CONDITIONS,
  347. where are selected areas (condtitions) stored
  348. \param f_cats_rasts_conds file which stores selected areas (conditions) from
  349. mapwindow see I_create_cat_rast and I_insert_patch_to_cat_rast
  350. \param bands_rows data arrays of raster rows from analyzed raster bands
  351. (all data in bands_rows and belongs_pix arrays represents same region (row))
  352. \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
  353. where are computed scatter plots stored
  354. \param[out] fd_cats_rasts array of opened raster maps,
  355. which every represents all selected pixels for category
  356. \return 0 on success
  357. \return -1 on failure
  358. */
  359. static int compute_scatts_from_chunk_row(struct scCats *scatt_conds,
  360. FILE ** f_cats_rasts_conds,
  361. struct rast_row *bands_rows,
  362. struct scCats *scatts,
  363. int *fd_cats_rasts)
  364. {
  365. int i_rows_pix, i_cat, i_scatt, n_pixs;
  366. int cat_id, scatt_plts_cat_idx, array_idx, max_arr_idx;
  367. char *b_1_null_row, *b_2_null_row;
  368. struct rast_row b_1_rast_row, b_2_rast_row;
  369. CELL *cat_rast_row;
  370. struct scScatts *scatts_conds;
  371. struct scScatts *scatts_scatt_plts;
  372. struct Range b_1_range, b_2_range;
  373. int b_1_range_size;
  374. int *scatts_bands;
  375. CELL *b_1_row;
  376. CELL *b_2_row;
  377. unsigned char *i_scatt_conds;
  378. int row_size = Rast_window_cols();
  379. unsigned short *belongs_pix =
  380. (unsigned short *)G_malloc(row_size * sizeof(unsigned short));
  381. unsigned char *rast_pixs =
  382. (unsigned char *)G_malloc(row_size * sizeof(unsigned char));
  383. cat_rast_row = Rast_allocate_c_buf();
  384. for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++) {
  385. scatts_conds = scatt_conds->cats_arr[i_cat];
  386. cat_id = scatt_conds->cats_ids[i_cat];
  387. scatt_plts_cat_idx = scatts->cats_idxs[cat_id];
  388. if (scatt_plts_cat_idx < 0)
  389. continue;
  390. scatts_scatt_plts = scatts->cats_arr[scatt_plts_cat_idx];
  391. G_zero(belongs_pix, row_size * sizeof(unsigned short));
  392. /* if category has no conditions defined, scatter plots without
  393. any constraint are computed (default scatter plots) */
  394. if (!scatts_conds->n_a_scatts && !f_cats_rasts_conds[i_cat]) {
  395. for (i_scatt = 0; i_scatt < scatts_scatt_plts->n_a_scatts;
  396. i_scatt++) {
  397. /* all pixels belongs */
  398. for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++)
  399. belongs_pix[i_rows_pix] = 1;
  400. }
  401. }
  402. /* compute belonging pixels for defined conditions */
  403. else {
  404. scatts_bands = scatts_conds->scatts_bands;
  405. /* check conditions from category raster condtitions file
  406. (see I_create_cat_rast) */
  407. if (f_cats_rasts_conds[i_cat]) {
  408. n_pixs =
  409. fread(rast_pixs, sizeof(unsigned char),
  410. (row_size) / sizeof(unsigned char),
  411. f_cats_rasts_conds[i_cat]);
  412. if (ferror(f_cats_rasts_conds[i_cat])) {
  413. G_free(rast_pixs);
  414. G_free(belongs_pix);
  415. G_warning(_
  416. ("Unable to read from category raster condtition file."));
  417. return -1;
  418. }
  419. if (n_pixs != n_pixs) {
  420. G_free(rast_pixs);
  421. G_free(belongs_pix);
  422. G_warning(_
  423. ("Invalid size of category raster conditions file."));
  424. return -1;
  425. }
  426. for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
  427. if (rast_pixs[i_rows_pix] != (0 & 255))
  428. belongs_pix[i_rows_pix] = 1;
  429. }
  430. }
  431. /* check condtions defined in scatter plots */
  432. for (i_scatt = 0; i_scatt < scatts_conds->n_a_scatts; i_scatt++) {
  433. b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
  434. b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
  435. b_1_row = b_1_rast_row.row;
  436. b_2_row = b_2_rast_row.row;
  437. b_1_null_row = b_1_rast_row.null_row;
  438. b_2_null_row = b_2_rast_row.null_row;
  439. b_1_range = b_1_rast_row.rast_range;
  440. b_2_range = b_2_rast_row.rast_range;
  441. b_1_range_size = b_1_range.max - b_1_range.min + 1;
  442. max_arr_idx =
  443. (b_1_range.max - b_1_range.min + 1) * (b_2_range.max -
  444. b_2_range.min + 1);
  445. i_scatt_conds =
  446. scatts_conds->scatts_arr[i_scatt]->b_conds_arr;
  447. for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
  448. /* pixels already belongs to category from category raster conditions
  449. file or contains null value in one of the bands */
  450. if (belongs_pix[i_rows_pix] ||
  451. b_1_null_row[i_rows_pix] == 1 ||
  452. b_2_null_row[i_rows_pix] == 1)
  453. continue;
  454. array_idx =
  455. b_1_row[i_rows_pix] - b_1_range.min +
  456. (b_2_row[i_rows_pix] -
  457. b_2_range.min) * b_1_range_size;
  458. if (array_idx < 0 || array_idx >= max_arr_idx) {
  459. G_warning(_("Data inconsistent. "
  460. "Value computed for scatter plot is out of initialized range."));
  461. continue;
  462. }
  463. /* pixels meets condtion defined in scatter plot ->
  464. belongs to scatter plot category */
  465. if (i_scatt_conds[array_idx])
  466. belongs_pix[i_rows_pix] = 1;
  467. }
  468. }
  469. }
  470. /* update category raster with belonging pixels */
  471. if (fd_cats_rasts[i_cat] >= 0) {
  472. Rast_set_null_value(cat_rast_row, Rast_window_cols(), CELL_TYPE);
  473. for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++)
  474. if (belongs_pix[i_rows_pix])
  475. cat_rast_row[i_rows_pix] = belongs_pix[i_rows_pix];
  476. Rast_put_c_row(fd_cats_rasts[i_cat], cat_rast_row);
  477. }
  478. /* update scatter plots with belonging pixels */
  479. update_cat_scatt_plts(bands_rows, belongs_pix, scatts_scatt_plts);
  480. }
  481. G_free(cat_rast_row);
  482. G_free(rast_pixs);
  483. G_free(belongs_pix);
  484. return 0;
  485. }
  486. /*!
  487. \brief Get list of bands needed to be opened for analysis from scCats struct.
  488. */
  489. static void get_needed_bands(struct scCats *cats, int *b_needed_bands)
  490. {
  491. /* results in b_needed_bands - array of bools - if item has value 1,
  492. band (defined by item index) is needed to be opened */
  493. int i_cat, i_scatt;
  494. for (i_cat = 0; i_cat < cats->n_a_cats; i_cat++) {
  495. for (i_scatt = 0; i_scatt < cats->cats_arr[i_cat]->n_a_scatts;
  496. i_scatt++) {
  497. G_debug(3, "Active scatt %d in catt %d", i_scatt, i_cat);
  498. b_needed_bands[cats->cats_arr[i_cat]->scatts_bands[i_scatt * 2]] =
  499. 1;
  500. b_needed_bands[cats->cats_arr[i_cat]->
  501. scatts_bands[i_scatt * 2 + 1]] = 1;
  502. }
  503. }
  504. return;
  505. }
  506. /*!
  507. \brief Helper function for clean up.
  508. */
  509. static void free_compute_scatts_data(int *fd_bands,
  510. struct rast_row *bands_rows,
  511. int n_a_bands, int *bands_ids,
  512. int *fd_cats_rasts,
  513. FILE ** f_cats_rasts_conds, int n_a_cats)
  514. {
  515. int i, band_id;
  516. for (i = 0; i < n_a_bands; i++) {
  517. band_id = bands_ids[i];
  518. if (band_id >= 0) {
  519. Rast_close(fd_bands[i]);
  520. G_free(bands_rows[band_id].row);
  521. G_free(bands_rows[band_id].null_row);
  522. }
  523. }
  524. if (f_cats_rasts_conds)
  525. for (i = 0; i < n_a_cats; i++)
  526. if (f_cats_rasts_conds[i])
  527. fclose(f_cats_rasts_conds[i]);
  528. if (fd_cats_rasts)
  529. for (i = 0; i < n_a_cats; i++)
  530. if (fd_cats_rasts[i] >= 0)
  531. Rast_close(fd_cats_rasts[i]);
  532. }
  533. /*!
  534. \brief Compute scatter plots data.
  535. If category has not defined category raster condition file and no scatter plot
  536. exists with condition, default/full scatter plot is computed.
  537. Warning: calls Rast_set_window
  538. \param region analysis region, beaware that all input data must be prepared for this region
  539. (bands (their ranges), cats_rasts_conds rasters...)
  540. \param region function calls Rast_set_window for this region
  541. \param scatt_conds pointer to scScatts struct of type SC_SCATT_CONDITIONS,
  542. where are stored selected areas (conditions) in scatter plots
  543. \param cats_rasts_conds paths to category raster conditions files representing
  544. selected areas from mapwindow (conditions) in rasters for every category
  545. \param cats_rasts_conds index in array represents corresponding category id
  546. \param cats_rasts_conds for manipulation with category raster conditions file
  547. see also I_id_scatt_to_bands and I_insert_patch_to_cat_rast
  548. \param bands names of analyzed bands, order of bands is defined by their id
  549. \param n_bands number of bands
  550. \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
  551. where are computed scatter plots stored
  552. \param[out] cats_rasts array of raster maps names for every category
  553. where will be stored all selected pixels
  554. \return 0 on success
  555. \return -1 on failure
  556. */
  557. int I_compute_scatts(struct Cell_head *region, struct scCats *scatt_conds,
  558. const char **cats_rasts_conds, const char **bands,
  559. int n_bands, struct scCats *scatts,
  560. const char **cats_rasts)
  561. {
  562. const char *mapset;
  563. char header[1024];
  564. int fd_cats_rasts[scatt_conds->n_a_cats];
  565. FILE *f_cats_rasts_conds[scatt_conds->n_a_cats];
  566. struct rast_row bands_rows[n_bands];
  567. RASTER_MAP_TYPE data_type;
  568. int nrows, i_band, n_a_bands, band_id;
  569. int i_row, head_nchars, i_cat, id_cat;
  570. int fd_bands[n_bands];
  571. int bands_ids[n_bands];
  572. int b_needed_bands[n_bands];
  573. Rast_set_window(region);
  574. for (i_band = 0; i_band < n_bands; i_band++)
  575. fd_bands[i_band] = -1;
  576. for (i_band = 0; i_band < n_bands; i_band++)
  577. bands_ids[i_band] = -1;
  578. if (n_bands != scatts->n_bands || n_bands != scatt_conds->n_bands)
  579. return -1;
  580. G_zero(b_needed_bands, (size_t) n_bands * sizeof(int));
  581. get_needed_bands(scatt_conds, &b_needed_bands[0]);
  582. get_needed_bands(scatts, &b_needed_bands[0]);
  583. n_a_bands = 0;
  584. /* open band rasters, which are needed for computation */
  585. for (band_id = 0; band_id < n_bands; band_id++) {
  586. if (b_needed_bands[band_id]) {
  587. G_debug(3, "Opening raster no. %d with name: %s", band_id,
  588. bands[band_id]);
  589. if ((mapset = G_find_raster2(bands[band_id], "")) == NULL) {
  590. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
  591. bands_ids, NULL, NULL,
  592. scatt_conds->n_a_cats);
  593. G_warning(_("Unbale to read find raster <%s>"),
  594. bands[band_id]);
  595. return -1;
  596. }
  597. if ((fd_bands[n_a_bands] =
  598. Rast_open_old(bands[band_id], mapset)) < 0) {
  599. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
  600. bands_ids, NULL, NULL,
  601. scatt_conds->n_a_cats);
  602. G_warning(_("Unbale to open raster <%s>"), bands[band_id]);
  603. return -1;
  604. }
  605. data_type = Rast_get_map_type(fd_bands[n_a_bands]);
  606. if (data_type != CELL_TYPE) {
  607. G_warning(_("Raster <%s> type is not <%s>"), bands[band_id],
  608. "CELL");
  609. return -1;
  610. }
  611. bands_rows[band_id].row = Rast_allocate_c_buf();
  612. bands_rows[band_id].null_row = Rast_allocate_null_buf();
  613. if (Rast_read_range
  614. (bands[band_id], mapset,
  615. &bands_rows[band_id].rast_range) != 1) {
  616. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
  617. bands_ids, NULL, NULL,
  618. scatt_conds->n_a_cats);
  619. G_warning(_("Unable to read range of raster <%s>"),
  620. bands[band_id]);
  621. return -1;
  622. }
  623. bands_ids[n_a_bands] = band_id;
  624. ++n_a_bands;
  625. }
  626. }
  627. /* open category rasters condition files and category rasters */
  628. for (i_cat = 0; i_cat < scatts->n_a_cats; i_cat++) {
  629. id_cat = scatts->cats_ids[i_cat];
  630. if (cats_rasts[id_cat]) {
  631. fd_cats_rasts[i_cat] =
  632. Rast_open_new(cats_rasts[id_cat], CELL_TYPE);
  633. }
  634. else
  635. fd_cats_rasts[i_cat] = -1;
  636. if (cats_rasts_conds[id_cat]) {
  637. f_cats_rasts_conds[i_cat] = fopen(cats_rasts_conds[id_cat], "r");
  638. if (!f_cats_rasts_conds[i_cat]) {
  639. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
  640. bands_ids, fd_cats_rasts,
  641. f_cats_rasts_conds,
  642. scatt_conds->n_a_cats);
  643. G_warning(_
  644. ("Unable to open category raster condtition file <%s>"),
  645. bands[band_id]);
  646. return -1;
  647. }
  648. }
  649. else
  650. f_cats_rasts_conds[i_cat] = NULL;
  651. }
  652. head_nchars = get_cat_rast_header(region, header);
  653. for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++)
  654. if (f_cats_rasts_conds[i_cat])
  655. if (fseek(f_cats_rasts_conds[i_cat], head_nchars, SEEK_SET) != 0) {
  656. G_warning(_
  657. ("Corrupted category raster conditions file (fseek failed)"));
  658. return -1;
  659. }
  660. nrows = Rast_window_rows();
  661. /* analyze bands by rows */
  662. for (i_row = 0; i_row < nrows; i_row++) {
  663. for (i_band = 0; i_band < n_a_bands; i_band++) {
  664. band_id = bands_ids[i_band];
  665. Rast_get_c_row(fd_bands[i_band], bands_rows[band_id].row, i_row);
  666. Rast_get_null_value_row(fd_bands[i_band],
  667. bands_rows[band_id].null_row, i_row);
  668. }
  669. if (compute_scatts_from_chunk_row
  670. (scatt_conds, f_cats_rasts_conds, bands_rows, scatts,
  671. fd_cats_rasts) == -1) {
  672. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
  673. bands_ids, fd_cats_rasts,
  674. f_cats_rasts_conds,
  675. scatt_conds->n_a_cats);
  676. return -1;
  677. }
  678. }
  679. free_compute_scatts_data(fd_bands, bands_rows, n_a_bands, bands_ids,
  680. fd_cats_rasts, f_cats_rasts_conds,
  681. scatt_conds->n_a_cats);
  682. return 0;
  683. }
  684. /*!
  685. \brief Merge arrays according to opacity.
  686. Every pixel in array must be represented by 4 values (RGBA).
  687. Implementd for speeding up of scatter plots rendering.
  688. \param merged_arr array which will be overlayd with overlay_arr
  689. \param overlay_arr array to be merged_arr overlaid with
  690. \param rows number of rows for the both arrays
  691. \param cols number of columns for the both arrays
  692. \param alpha transparency (0-1) of the overlay array for merging
  693. \return 0
  694. */
  695. int I_merge_arrays(unsigned char *merged_arr, unsigned char *overlay_arr,
  696. unsigned rows, unsigned cols, double alpha)
  697. {
  698. unsigned int i_row, i_col, i_b;
  699. unsigned int row_idx, col_idx, idx;
  700. unsigned int c_a_i, c_a;
  701. for (i_row = 0; i_row < rows; i_row++) {
  702. row_idx = i_row * cols;
  703. for (i_col = 0; i_col < cols; i_col++) {
  704. col_idx = 4 * (row_idx + i_col);
  705. idx = col_idx + 3;
  706. c_a = overlay_arr[idx] * alpha;
  707. c_a_i = 255 - c_a;
  708. merged_arr[idx] =
  709. (c_a_i * (int)merged_arr[idx] + c_a * 255) / 255;
  710. for (i_b = 0; i_b < 3; i_b++) {
  711. idx = col_idx + i_b;
  712. merged_arr[idx] =
  713. (c_a_i * (int)merged_arr[idx] +
  714. c_a * (int)overlay_arr[idx]) / 255;
  715. }
  716. }
  717. }
  718. return 0;
  719. }
  720. /*!
  721. \brief Apply colromap to the raster.
  722. Implementd for speeding up of scatter plots rendering.
  723. \param vals array of values for applying the colormap
  724. \param vals_mask maks of vals array
  725. \param nvals number of items of vals_mask and vals array
  726. \param colmap colour map to be applied
  727. \param[out] col_vals output raster with applied color map (length is 4 * nvals (RGBA))
  728. \return 0
  729. */
  730. int I_apply_colormap(unsigned char *vals, unsigned char *vals_mask,
  731. unsigned nvals, unsigned char *colmap,
  732. unsigned char *col_vals)
  733. {
  734. unsigned int i_val;
  735. int v, i, i_cm;
  736. for (i_val = 0; i_val < nvals; i_val++) {
  737. i_cm = 4 * i_val;
  738. v = vals[i_val];
  739. if (vals_mask && vals_mask[i_val])
  740. for (i = 0; i < 4; i++)
  741. col_vals[i_cm + i] = colmap[258 * 4 + i];
  742. else if (v > 255)
  743. for (i = 0; i < 4; i++)
  744. col_vals[i_cm + i] = colmap[257 * 4 + i];
  745. else if (v < 0)
  746. for (i = 0; i < 4; i++)
  747. col_vals[i_cm + i] = colmap[256 * 4 + i];
  748. else
  749. for (i = 0; i < 4; i++) {
  750. col_vals[i_cm + i] = colmap[v * 4 + i];
  751. }
  752. }
  753. return 0;
  754. }
  755. /*!
  756. \brief Wrapper for using of iclass perimeter rasterization by scatter plot.
  757. Warning: calls Rast_set_window
  758. \param polygon array of polygon coordinates [x, y, x, y...]
  759. \param pol_n_pts number of points in the polygon array
  760. \param val value to be assigned to cells, which belong to plygon
  761. \param rast_region region of raster
  762. \param[out] rast raster to be pologyn rasterized in
  763. \return 0 on success
  764. \return 1 on failure
  765. */
  766. int I_rasterize(double *polygon, int pol_n_pts, unsigned char val,
  767. struct Cell_head *rast_region, unsigned char *rast)
  768. {
  769. int i;
  770. int x0, x1, y;
  771. int row, row_idx, i_col;
  772. IClass_perimeter perimeter;
  773. struct line_pnts *pol;
  774. pol = Vect_new_line_struct();
  775. for (i = 0; i < pol_n_pts; i++) {
  776. Vect_append_point(pol, polygon[i * 2], polygon[i * 2 + 1], 0.0);
  777. }
  778. /* Rast_set_window(rast_region); */
  779. make_perimeter(pol, &perimeter, rast_region);
  780. for (i = 1; i < perimeter.npoints; i += 2) {
  781. y = perimeter.points[i].y;
  782. if (y != perimeter.points[i - 1].y) {
  783. G_warning(_
  784. ("prepare_signature: scan line %d has odd number of points."),
  785. (i + 1) / 2);
  786. return 1;
  787. }
  788. x0 = perimeter.points[i - 1].x;
  789. x1 = perimeter.points[i].x;
  790. if (x0 > x1) {
  791. G_warning(_("signature: perimeter points out of order."));
  792. return 1;
  793. }
  794. row = (rast_region->rows - y);
  795. if (row < 0 || row >= rast_region->rows) {
  796. continue;
  797. }
  798. row_idx = rast_region->cols * row;
  799. for (i_col = x0; i_col <= x1; i_col++) {
  800. if (i_col < 0 || i_col >= rast_region->cols) {
  801. continue;
  802. }
  803. rast[row_idx + i_col] = val;
  804. }
  805. }
  806. Vect_destroy_line_struct(pol);
  807. G_free(perimeter.points);
  808. return 0;
  809. }