GRASS 8 Programmer's Manual 8.6.0dev(2026)-f6f2c534ea
Loading...
Searching...
No Matches
iscatt_core.c
Go to the documentation of this file.
1/*!
2 \file lib/imagery/iscatt_core.c
3
4 \brief Imagery library - wx.iscatt (wx Interactive Scatter Plot Tool)
5 backend.
6
7 Copyright (C) 2013 by the GRASS Development Team
8
9 This program is free software under the GNU General Public License
10 (>=v2). Read the file COPYING that comes with GRASS for details.
11
12 \author Stepan Turek <stepan.turek@seznam.cz> (GSoC 2013, Mentor: Martin
13 Landa)
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <math.h>
19
20#include <grass/gis.h>
21#include <grass/vector.h>
22#include <grass/raster.h>
23#include <grass/imagery.h>
24#include <grass/glocale.h>
25
26#include "iclass_local_proto.h"
27
28struct rast_row {
29 CELL *row;
30 char *null_row;
31 struct Range rast_range; /*Range of whole raster. */
32};
33
34/*!
35 \brief Create pgm header.
36
37 Scatter plot internally generates pgm files.
38 These pgms have header in format created by this function.
39
40 \param region region to be pgm header generated for
41 \param[out] header header of pgm file
42 */
43static int get_cat_rast_header(struct Cell_head *region, char *header)
44{
45 return sprintf(header, "P5\n%d\n%d\n1\n", region->cols, region->rows);
46}
47
48/*!
49 \brief Create category raster conditions file.
50 The file is used for holding selected areas from mapwindow.
51 The reason why the standard GRASS raster is not used is that for every
52 modification (new area is selected) we would need to create whole new raster.
53 Instead of this scatter plot only modifies affected region in
54 the internal pgm file.
55
56 \param cat_rast_region region to be file generated for
57 \param[out] cat_rast path where the pgm raster file will be generated
58 */
60{
62 char cat_rast_header[1024]; /* TODO magic number */
63 int i_row, i_col;
64 int head_nchars;
65
66 unsigned char *row_data;
67
68 f_cat_rast = fopen(cat_rast, "wb");
69 if (!f_cat_rast) {
70 G_warning("Unable to create category raster condition file <%s>.",
71 cat_rast);
72 return -1;
73 }
74
75 head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
76
77 fwrite(cat_rast_header, sizeof(char), head_nchars / sizeof(char),
79 if (ferror(f_cat_rast)) {
81 G_warning(_("Unable to write header into category raster condition "
82 "file <%s>."),
83 cat_rast);
84 return -1;
85 }
86
87 row_data = (unsigned char *)G_malloc(cat_rast_region->cols *
88 sizeof(unsigned char));
89 for (i_col = 0; i_col < cat_rast_region->cols; i_col++)
90 row_data[i_col] = 0 & 255;
91
92 for (i_row = 0; i_row < cat_rast_region->rows; i_row++) {
93 fwrite(row_data, sizeof(unsigned char),
94 (cat_rast_region->cols) / sizeof(unsigned char), f_cat_rast);
95 if (ferror(f_cat_rast)) {
99 _("Unable to write into category raster condition file <%s>."),
100 cat_rast);
101 return -1;
102 }
103 }
104
107 return 0;
108}
109
110/*!
111 \brief Find intersection region of two regions.
112
113 \param A pointer to intersected region
114 \param B pointer to intersected region
115 \param[out] intersec pointer to intersection region of regions A B
116 (relevant params of the region are: south, north, east, west)
117
118 \return 0 if interaction exists
119 \return -1 if regions does not intersect
120 */
121static int regions_intersecion(struct Cell_head *A, struct Cell_head *B,
122 struct Cell_head *intersec)
123{
124
125 if (B->north < A->south)
126 return -1;
127 else if (B->north > A->north)
128 intersec->north = A->north;
129 else
130 intersec->north = B->north;
131
132 if (B->south > A->north)
133 return -1;
134 else if (B->south < A->south)
135 intersec->south = A->south;
136 else
137 intersec->south = B->south;
138
139 if (B->east < A->west)
140 return -1;
141 else if (B->east > A->east)
142 intersec->east = A->east;
143 else
144 intersec->east = B->east;
145
146 if (B->west > A->east)
147 return -1;
148 else if (B->west < A->west)
149 intersec->west = A->west;
150 else
151 intersec->west = B->west;
152
153 if (intersec->north == intersec->south)
154 return -1;
155
156 if (intersec->east == intersec->west)
157 return -1;
158
159 return 0;
160}
161
162/*!
163 \brief Get rows and cols numbers, which defines intersection of the regions.
164
165 \param A pointer to intersected region
166 \param B pointer to intersected region (A and B must have same resolution)
167 \param[out] A_bounds rows and cols numbers of A stored in
168 south, north, east, west, which defines intersection of A and B
169 \param[out] B_bounds rows and cols numbers of B stored in
170 south, north, east, west, which defines intersection of A and B
171
172 \return 0 if interaction exists
173 \return -1 if regions do not intersect
174 \return -2 resolution of regions is not same
175 */
176static int get_rows_and_cols_bounds(struct Cell_head *A, struct Cell_head *B,
177 struct Cell_head *A_bounds,
178 struct Cell_head *B_bounds)
179{
180 float ns_res, ew_res;
181
182 struct Cell_head intersec;
183
184 /* TODO is it right check? */
185 if (fabs(A->ns_res - B->ns_res) > GRASS_EPSILON) {
186 G_warning("'get_rows_and_cols_bounds' ns_res does not fit, A->ns_res: "
187 "%f B->ns_res: %f",
188 A->ns_res, B->ns_res);
189 return -2;
190 }
191
192 if (fabs(A->ew_res - B->ew_res) > GRASS_EPSILON) {
193 G_warning("'get_rows_and_cols_bounds' ew_res does not fit, A->ew_res: "
194 "%f B->ew_res: %f",
195 A->ew_res, B->ew_res);
196 return -2;
197 }
198
199 ns_res = A->ns_res;
200 ew_res = A->ew_res;
201
202 if (regions_intersecion(A, B, &intersec) == -1)
203 return -1;
204
205 A_bounds->north = ceil((A->north - intersec.north - ns_res * 0.5) / ns_res);
206 A_bounds->south = ceil((A->north - intersec.south - ns_res * 0.5) / ns_res);
207
208 A_bounds->east = ceil((intersec.east - A->west - ew_res * 0.5) / ew_res);
209 A_bounds->west = ceil((intersec.west - A->west - ew_res * 0.5) / ew_res);
210
211 B_bounds->north = ceil((B->north - intersec.north - ns_res * 0.5) / ns_res);
212 B_bounds->south = ceil((B->north - intersec.south - ns_res * 0.5) / ns_res);
213
214 B_bounds->east = ceil((intersec.east - B->west - ew_res * 0.5) / ew_res);
215 B_bounds->west = ceil((intersec.west - B->west - ew_res * 0.5) / ew_res);
216
217 return 0;
218}
219
220/*!
221 \brief Insert raster map patch into pgm file.
222 \see I_create_cat_rast
223
224 Warning: calls Rast_set_window
225
226 \param patch_rast name of raster map
227 \param cat_rast_region region of category raster file
228 \param cat_rast path to category raster file
229
230 \return 0 on success
231 \return -1 on failure
232 */
235 const char *cat_rast)
236{
237
240 char cat_rast_header[1024];
241 int i_row, i_col, ncols, nrows, patch_col;
242 int head_nchars, ret;
244 unsigned char *patch_data;
245
246 char *null_chunk_row;
247
248 const char *mapset;
249
250 f_cat_rast = fopen(cat_rast, "rb+");
251 if (!f_cat_rast) {
252 G_warning(_("Unable to open category raster conditions file <%s>."),
253 cat_rast);
254 return -1;
255 }
256
257 head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
258 if ((mapset = G_find_raster((char *)patch_rast, "")) == NULL) {
260 G_warning(_("Unable to find patch raster <%s>."), patch_rast);
261 return -1;
262 }
263
266
267 if ((fd_patch_rast = Rast_open_old(patch_rast, mapset)) < 0) {
269 return -1;
270 }
271
272 ret = get_rows_and_cols_bounds(cat_rast_region, &patch_region,
274 if (ret == -2) {
275 G_warning(
276 _("Resolutions of patch <%s> and patched file <%s> are not same."),
278
281
282 return -1;
283 }
284 else if (ret == -1) {
285
288
289 return 0;
290 }
291
292 ncols = cat_rast_bounds.east - cat_rast_bounds.west;
293 nrows = cat_rast_bounds.south - cat_rast_bounds.north;
294
295 patch_data = (unsigned char *)G_malloc(ncols * sizeof(unsigned char));
296
298 cat_rast_bounds.west;
299
300 if (fseek(f_cat_rast, init_shift, SEEK_SET) != 0) {
301 G_warning(
302 _("Corrupted category raster conditions file <%s> (fseek failed)"),
303 cat_rast);
304
308
309 return -1;
310 }
311
312 step_shift = cat_rast_region->cols - ncols;
313
315
316 for (i_row = 0; i_row < nrows; i_row++) {
318 i_row + patch_bounds.north);
319
320 for (i_col = 0; i_col < ncols; i_col++) {
322
323 if (null_chunk_row[patch_col] != 1)
324 patch_data[i_col] = 1 & 255;
325 else {
326 patch_data[i_col] = 0 & 255;
327 }
328 }
329
330 fwrite(patch_data, sizeof(unsigned char),
331 (ncols) / sizeof(unsigned char), f_cat_rast);
332 if (ferror(f_cat_rast)) {
333 G_warning(
334 _("Unable to write into category raster conditions file <%s>"),
335 cat_rast);
336
341
342 return -1;
343 }
344 if (fseek(f_cat_rast, step_shift, SEEK_CUR) != 0) {
345 G_warning(_("Corrupted category raster conditions file <%s> "
346 "(fseek failed)"),
347 cat_rast);
348
353
354 return -1;
355 }
356 }
357
362 return 0;
363}
364
365/*!
366 \brief Updates scatter plots data in category by pixels which meets category
367 conditions.
368
369 \param bands_rows data represents data describig one row from raster band
370 \param belongs_pix array which defines which pixels belongs to category
371 (1 value) and which not (0 value)
372 \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
373 which are modified according to values in belongs_pix
374 (represents scatter plot category)
375 */
376static void update_cat_scatt_plts(struct rast_row *bands_rows,
377 unsigned short *belongs_pix,
378 struct scScatts *scatts)
379{
381
382 CELL *b_1_row;
383 CELL *b_2_row;
385 struct rast_row b_1_rast_row, b_2_rast_row;
386
387 struct Range b_1_range, b_2_range;
388 int b_1_range_size;
389
391
392 int *scatts_bands = scatts->scatts_bands;
393
394 for (i_scatt = 0; i_scatt < scatts->n_a_scatts; i_scatt++) {
395 b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
396 b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
397
398 b_1_row = b_1_rast_row.row;
399 b_2_row = b_2_rast_row.row;
400
401 b_1_null_row = b_1_rast_row.null_row;
402 b_2_null_row = b_2_rast_row.null_row;
403
404 b_1_range = b_1_rast_row.rast_range;
405 b_2_range = b_2_rast_row.rast_range;
406
407 b_1_range_size = b_1_range.max - b_1_range.min + 1;
408 max_arr_idx = (b_1_range.max - b_1_range.min + 1) *
409 (b_2_range.max - b_2_range.min + 1);
410
413 /* pixel does not belongs to scatter plot or has null value in one
414 * of the bands */
418 continue;
419
420 /* index in scatter plot array */
421 array_idx =
424
426 G_warning("Inconsistent data. Value computed for scatter plot "
427 "is out of initialized range.");
428 continue;
429 }
430
431 /* increment scatter plot value */
432 ++scatts->scatts_arr[i_scatt]->scatt_vals_arr[array_idx];
433 }
434 }
435}
436
437/*!
438 \brief Computes scatter plots data from bands_rows.
439
440 \param scatt_conds pointer to scScatts struct of type SC_SCATT_CONDITIONS,
441 where are selected areas (conditions) stored
442 \param f_cats_rasts_conds file which stores selected areas (conditions) from
443 mapwindow see I_create_cat_rast and I_insert_patch_to_cat_rast
444 \param bands_rows data arrays of raster rows from analyzed raster bands
445 (all data in bands_rows and belongs_pix arrays represents same region (row))
446 \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
447 where are computed scatter plots stored
448 \param[out] fd_cats_rasts array of opened raster maps,
449 which every represents all selected pixels for category
450
451 \return 0 on success
452 \return -1 on failure
453 */
454static int compute_scatts_from_chunk_row(struct scCats *scatt_conds,
456 struct rast_row *bands_rows,
457 struct scCats *scatts,
458 int *fd_cats_rasts)
459{
460
464 struct rast_row b_1_rast_row, b_2_rast_row;
466
467 struct scScatts *scatts_conds;
469
470 struct Range b_1_range, b_2_range;
471 int b_1_range_size;
472
473 int *scatts_bands;
474
475 CELL *b_1_row;
476 CELL *b_2_row;
477 unsigned char *i_scatt_conds;
478
480
481 unsigned short *belongs_pix =
482 (unsigned short *)G_malloc(row_size * sizeof(unsigned short));
483 unsigned char *rast_pixs =
484 (unsigned char *)G_malloc(row_size * sizeof(unsigned char));
486
487 for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++) {
488 scatts_conds = scatt_conds->cats_arr[i_cat];
489
490 cat_id = scatt_conds->cats_ids[i_cat];
491
492 scatt_plts_cat_idx = scatts->cats_idxs[cat_id];
493 if (scatt_plts_cat_idx < 0)
494 continue;
496
497 G_zero(belongs_pix, row_size * sizeof(unsigned short));
498
499 /* if category has no conditions defined, scatter plots without
500 any constraint are computed (default scatter plots) */
501 if (!scatts_conds->n_a_scatts && !f_cats_rasts_conds[i_cat]) {
502 for (i_scatt = 0; i_scatt < scatts_scatt_plts->n_a_scatts;
503 i_scatt++) {
504 /* all pixels belongs */
507 }
508 }
509 /* compute belonging pixels for defined conditions */
510 else {
511 scatts_bands = scatts_conds->scatts_bands;
512
513 /* check conditions from category raster conditions file
514 (see I_create_cat_rast) */
516 n_pixs = fread(rast_pixs, sizeof(unsigned char),
517 (row_size) / sizeof(unsigned char),
519
523 G_warning(_(
524 "Unable to read from category raster condition file."));
525 return -1;
526 }
527 if (n_pixs != (row_size) / (int)sizeof(unsigned char)) {
530 G_warning(
531 _("Invalid size of category raster conditions file."));
532 return -1;
533 }
534
535 for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
536 if (rast_pixs[i_rows_pix] != (0 & 255))
538 }
539 }
540
541 /* check conditions defined in scatter plots */
542 for (i_scatt = 0; i_scatt < scatts_conds->n_a_scatts; i_scatt++) {
543 b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
544 b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
545
546 b_1_row = b_1_rast_row.row;
547 b_2_row = b_2_rast_row.row;
548
549 b_1_null_row = b_1_rast_row.null_row;
550 b_2_null_row = b_2_rast_row.null_row;
551
552 b_1_range = b_1_rast_row.rast_range;
553 b_2_range = b_2_rast_row.rast_range;
554
555 b_1_range_size = b_1_range.max - b_1_range.min + 1;
556 max_arr_idx = (b_1_range.max - b_1_range.min + 1) *
557 (b_2_range.max - b_2_range.min + 1);
558
559 i_scatt_conds = scatts_conds->scatts_arr[i_scatt]->b_conds_arr;
560
561 for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
562 /* pixels already belongs to category from category raster
563 conditions file or contains null value in one of the
564 bands */
565 if (belongs_pix[i_rows_pix] ||
566 b_1_null_row[i_rows_pix] == 1 ||
568 continue;
569
570 array_idx =
574 G_warning(_("Data inconsistent. "
575 "Value computed for scatter plot is out of "
576 "initialized range."));
577 continue;
578 }
579 /* pixels meets condition defined in scatter plot ->
580 belongs to scatter plot category */
583 }
584 }
585 }
586
587 /* update category raster with belonging pixels */
588 if (fd_cats_rasts[i_cat] >= 0) {
590
594
596 }
597
598 /* update scatter plots with belonging pixels */
599 update_cat_scatt_plts(bands_rows, belongs_pix, scatts_scatt_plts);
600 }
601
605
606 return 0;
607}
608
609/*!
610 \brief Get list of bands needed to be opened for analysis from scCats struct.
611 */
612static void get_needed_bands(struct scCats *cats, int *b_needed_bands)
613{
614 /* results in b_needed_bands - array of bools - if item has value 1,
615 band (defined by item index) is needed to be opened */
616 int i_cat, i_scatt;
617
618 for (i_cat = 0; i_cat < cats->n_a_cats; i_cat++) {
619 for (i_scatt = 0; i_scatt < cats->cats_arr[i_cat]->n_a_scatts;
620 i_scatt++) {
621 G_debug(3, "Active scatt %d in catt %d", i_scatt, i_cat);
622
623 b_needed_bands[cats->cats_arr[i_cat]->scatts_bands[i_scatt * 2]] =
624 1;
626 ->scatts_bands[i_scatt * 2 + 1]] = 1;
627 }
628 }
629 return;
630}
631
632/*!
633 \brief Helper function for clean up.
634 */
635static void free_compute_scatts_data(int *fd_bands, struct rast_row *bands_rows,
636 int n_a_bands, int *bands_ids,
637 int *b_needed_bands, int *fd_cats_rasts,
638 FILE **f_cats_rasts_conds, int n_a_cats)
639{
640 for (int i = 0; i < n_a_bands; i++) {
641 int band_id = bands_ids[i];
642 if (band_id >= 0) {
645 G_free(bands_rows[band_id].null_row);
646 }
647 }
648
649 for (int i = 0; i < n_a_cats; i++)
650 if (f_cats_rasts_conds[i])
652
653 for (int i = 0; i < n_a_cats; i++)
654 if (fd_cats_rasts[i] >= 0)
656
663}
664
665/*!
666 \brief Compute scatter plots data.
667
668 If category has not defined category raster condition file and no scatter
669 plot exists with condition, default/full scatter plot is computed. Warning:
670 calls Rast_set_window
671
672 \param region analysis region, beaware that all input data must be prepared
673 for this region (bands (their ranges), cats_rasts_conds rasters...) \param
674 region function calls Rast_set_window for this region \param scatt_conds
675 pointer to scScatts struct of type SC_SCATT_CONDITIONS, where are stored
676 selected areas (conditions) in scatter plots \param cats_rasts_conds paths to
677 category raster conditions files representing selected areas from mapwindow
678 (conditions) in rasters for every category \param cats_rasts_conds index in
679 array represents corresponding category id \param cats_rasts_conds for
680 manipulation with category raster conditions file see also
681 I_id_scatt_to_bands and I_insert_patch_to_cat_rast \param bands names of
682 analyzed bands, order of bands is defined by their id \param n_bands number
683 of bands \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
684 where are computed scatter plots stored
685 \param[out] cats_rasts array of raster maps names for every category
686 where will be stored all selected pixels
687
688 \return 0 on success
689 \return -1 on failure
690 */
691int I_compute_scatts(struct Cell_head *region, struct scCats *scatt_conds,
692 const char **cats_rasts_conds, const char **bands,
693 int n_bands, struct scCats *scatts,
694 const char **cats_rasts)
695{
696 const char *mapset;
697 char header[1024];
698 if (n_bands != scatts->n_bands || n_bands != scatt_conds->n_bands) {
699 return -1;
700 }
701
702 int *fd_cats_rasts = G_malloc(scatt_conds->n_a_cats * sizeof(int));
704 G_malloc(scatt_conds->n_a_cats * sizeof(FILE *));
705
706 struct rast_row *bands_rows = G_malloc(n_bands * sizeof(struct rast_row));
707
708 RASTER_MAP_TYPE data_type;
709 int nrows, i_band, n_a_bands = 0, band_id;
711
712 int *fd_bands = G_malloc(n_bands * sizeof(int));
713 int *bands_ids = G_malloc(n_bands * sizeof(int));
714 int *b_needed_bands = G_malloc(n_bands * sizeof(int));
715
716 Rast_set_window(region);
717
718 for (i_band = 0; i_band < n_bands; i_band++)
719 fd_bands[i_band] = -1;
720
721 for (i_band = 0; i_band < n_bands; i_band++)
722 bands_ids[i_band] = -1;
723 for (i_cat = 0; i_cat < scatts->n_a_cats; i_cat++)
724 fd_cats_rasts[i_cat] = -1;
725
726 G_zero(b_needed_bands, (size_t)n_bands * sizeof(int));
727
728 get_needed_bands(scatt_conds, &b_needed_bands[0]);
729 get_needed_bands(scatts, &b_needed_bands[0]);
730
731 /* open band rasters, which are needed for computation */
732 for (band_id = 0; band_id < n_bands; band_id++) {
733 if (b_needed_bands[band_id]) {
734 G_debug(3, "Opening raster no. %d with name: %s", band_id,
735 bands[band_id]);
736
737 if ((mapset = G_find_raster2(bands[band_id], "")) == NULL) {
738 free_compute_scatts_data(
741 G_warning(_("Unable to find raster <%s>"), bands[band_id]);
742 return -1;
743 }
744
745 if ((fd_bands[n_a_bands] = Rast_open_old(bands[band_id], mapset)) <
746 0) {
747 free_compute_scatts_data(
750 G_warning(_("Unable to open raster <%s>"), bands[band_id]);
751 return -1;
752 }
753
755 if (data_type != CELL_TYPE) {
756 free_compute_scatts_data(
759 G_warning(_("Raster <%s> type is not <%s>"), bands[band_id],
760 "CELL");
761 return -1;
762 }
763
766
767 if (Rast_read_range(bands[band_id], mapset,
768 &bands_rows[band_id].rast_range) != 1) {
769 free_compute_scatts_data(
772 G_warning(_("Unable to read range of raster <%s>"),
773 bands[band_id]);
774 return -1;
775 }
776
778 ++n_a_bands;
779 }
780 }
781
782 /* open category rasters condition files and category rasters */
783 for (i_cat = 0; i_cat < scatts->n_a_cats; i_cat++) {
784 id_cat = scatts->cats_ids[i_cat];
785 if (cats_rasts[id_cat]) {
787 }
788
792 free_compute_scatts_data(
795 G_warning(
796 _("Unable to open category raster condition file <%s>"),
797 bands[band_id]);
798 return -1;
799 }
800 }
801 else
803 }
804
805 head_nchars = get_cat_rast_header(region, header);
806 for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++)
809 free_compute_scatts_data(
812 G_warning(_("Corrupted category raster conditions file (fseek "
813 "failed)"));
814 return -1;
815 }
816
817 nrows = Rast_window_rows();
818
819 /* analyze bands by rows */
820 for (i_row = 0; i_row < nrows; i_row++) {
821 for (i_band = 0; i_band < n_a_bands; i_band++) {
825 bands_rows[band_id].null_row, i_row);
826 }
827 if (compute_scatts_from_chunk_row(scatt_conds, f_cats_rasts_conds,
829 fd_cats_rasts) == -1) {
830 free_compute_scatts_data(fd_bands, bands_rows, n_a_bands, bands_ids,
833 return -1;
834 }
835 }
836 free_compute_scatts_data(fd_bands, bands_rows, n_a_bands, bands_ids,
838 scatt_conds->n_a_cats);
839 return 0;
840}
841
842/*!
843 \brief Merge arrays according to opacity.
844 Every pixel in array must be represented by 4 values (RGBA).
845
846 Implemented for speeding up of scatter plots rendering.
847
848 \param merged_arr array which will be overlayd with overlay_arr
849 \param overlay_arr array to be merged_arr overlaid with
850 \param rows number of rows for the both arrays
851 \param cols number of columns for the both arrays
852 \param alpha transparency (0-1) of the overlay array for merging
853
854 \return 0
855 */
856int I_merge_arrays(unsigned char *merged_arr, unsigned char *overlay_arr,
857 unsigned rows, unsigned cols, double alpha)
858{
859 unsigned int i_row, i_col, i_b;
860 unsigned int row_idx, col_idx, idx;
861 unsigned int c_a_i, c_a;
862
863 for (i_row = 0; i_row < rows; i_row++) {
864 row_idx = i_row * cols;
865 for (i_col = 0; i_col < cols; i_col++) {
866 col_idx = 4 * (row_idx + i_col);
867 idx = col_idx + 3;
868
869 c_a = overlay_arr[idx] * alpha;
870 c_a_i = 255 - c_a;
871
872 merged_arr[idx] = (c_a_i * (int)merged_arr[idx] + c_a * 255) / 255;
873
874 for (i_b = 0; i_b < 3; i_b++) {
875 idx = col_idx + i_b;
876 merged_arr[idx] = (c_a_i * (int)merged_arr[idx] +
877 c_a * (int)overlay_arr[idx]) /
878 255;
879 }
880 }
881 }
882 return 0;
883}
884
885/*!
886 \brief Apply colromap to the raster.
887
888 Implemented for speeding up of scatter plots rendering.
889
890 \param vals array of values for applying the colormap
891 \param vals_mask mask of vals array
892 \param nvals number of items of vals_mask and vals array
893 \param colmap colour map to be applied
894 \param[out] col_vals output raster with applied color map (length is 4 *
895 nvals (RGBA))
896
897 \return 0
898 */
899int I_apply_colormap(unsigned char *vals, unsigned char *vals_mask,
900 unsigned nvals, unsigned char *colmap,
901 unsigned char *col_vals)
902{
903 unsigned int i_val;
904 int v, i, i_cm;
905
906 for (i_val = 0; i_val < nvals; i_val++) {
907 i_cm = 4 * i_val;
908
909 v = vals[i_val];
910
911 if (vals_mask && vals_mask[i_val])
912 for (i = 0; i < 4; i++)
913 col_vals[i_cm + i] = colmap[258 * 4 + i];
914 else if (v > 255)
915 for (i = 0; i < 4; i++)
916 col_vals[i_cm + i] = colmap[257 * 4 + i];
917 else if (v < 0)
918 for (i = 0; i < 4; i++)
919 col_vals[i_cm + i] = colmap[256 * 4 + i];
920 else
921 for (i = 0; i < 4; i++) {
922 col_vals[i_cm + i] = colmap[v * 4 + i];
923 }
924 }
925 return 0;
926}
927
928/*!
929 \brief Wrapper for using of iclass perimeter rasterization by scatter plot.
930 Warning: calls Rast_set_window
931
932 \param polygon array of polygon coordinates [x, y, x, y...]
933 \param pol_n_pts number of points in the polygon array
934 \param val value to be assigned to cells, which belong to plygon
935 \param rast_region region of raster
936 \param[out] rast raster to be pologyn rasterized in
937
938 \return 0 on success
939 \return 1 on failure
940 */
941int I_rasterize(double *polygon, int pol_n_pts, unsigned char val,
942 struct Cell_head *rast_region, unsigned char *rast)
943{
944 int i;
945 int x0, x1, y;
946 int row, row_idx, i_col;
947
949
950 struct line_pnts *pol;
951
953
954 for (i = 0; i < pol_n_pts; i++) {
955 Vect_append_point(pol, polygon[i * 2], polygon[i * 2 + 1], 0.0);
956 }
957
958 /* Rast_set_window(rast_region); */
959
961 for (i = 1; i < perimeter.npoints; i += 2) {
962 y = perimeter.points[i].y;
963 if (y != perimeter.points[i - 1].y) {
964 G_warning(
965 _("prepare_signature: scan line %d has odd number of points."),
966 (i + 1) / 2);
968 G_free(perimeter.points);
969 return 1;
970 }
971
972 x0 = perimeter.points[i - 1].x;
973 x1 = perimeter.points[i].x;
974
975 if (x0 > x1) {
976 G_warning(_("signature: perimeter points out of order."));
978 G_free(perimeter.points);
979 return 1;
980 }
981
982 row = (rast_region->rows - y);
983 if (row < 0 || row >= rast_region->rows) {
984 continue;
985 }
986
987 row_idx = rast_region->cols * row;
988
989 for (i_col = x0; i_col <= x1; i_col++) {
991 continue;
992 }
993 rast[row_idx + i_col] = val;
994 }
995 }
996
998 G_free(perimeter.points);
999 return 0;
1000}
#define NULL
Definition ccmath.h:32
const char * G_find_raster(char *, const char *)
Find a raster map.
Definition find_rast.c:55
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:23
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:139
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_find_raster2(const char *, const char *)
Find a raster map (look but don't touch)
Definition find_rast.c:76
CELL * Rast_allocate_c_buf(void)
Allocate memory for a CELL type raster map.
Definition alloc_cell.c:80
void Rast_close(int)
Close a raster map.
int Rast_open_old(const char *, const char *)
Open an existing integer raster map (cell)
void Rast_get_c_row(int, CELL *, int)
Get raster row (CELL type)
int Rast_open_new(const char *, RASTER_MAP_TYPE)
Opens a new raster map.
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
char * Rast_allocate_null_buf(void)
Allocates memory for a null buffer.
Definition alloc_cell.c:119
int Rast_window_cols(void)
Number of columns in active window.
int Rast_window_rows(void)
Number of rows in active window.
void Rast_set_null_value(void *, int, RASTER_MAP_TYPE)
To set one or more raster values to null.
Definition null_val.c:98
void Rast_put_c_row(int, const CELL *)
Writes the next row for cell file (CELL version)
void Rast_set_window(struct Cell_head *)
Establishes 'window' as the current working window.
void Rast_get_cellhd(const char *, const char *, struct Cell_head *)
Read the raster header.
Definition get_cellhd.c:41
void Rast_get_null_value_row(int, char *, int)
Read or simulate null value row.
RASTER_MAP_TYPE Rast_get_map_type(int)
Determine raster type from descriptor.
void Vect_destroy_line_struct(struct line_pnts *)
Frees all memory associated with a line_pnts structure, including the structure itself.
Definition line.c:77
struct line_pnts * Vect_new_line_struct(void)
Creates and initializes a line_pnts structure.
Definition line.c:45
int Vect_append_point(struct line_pnts *, double, double, double)
Appends one point to the end of a line.
Definition line.c:148
#define GRASS_EPSILON
Definition gis.h:178
int CELL
Definition gis.h:634
#define _(str)
Definition glocale.h:10
int make_perimeter(struct line_pnts *points, IClass_perimeter *perimeter, struct Cell_head *band_region)
Creates one perimeter from vector area.
int I_apply_colormap(unsigned char *vals, unsigned char *vals_mask, unsigned nvals, unsigned char *colmap, unsigned char *col_vals)
Apply colromap to the raster.
int I_create_cat_rast(struct Cell_head *cat_rast_region, const char *cat_rast)
Create category raster conditions file. The file is used for holding selected areas from mapwindow....
Definition iscatt_core.c:59
int I_compute_scatts(struct Cell_head *region, struct scCats *scatt_conds, const char **cats_rasts_conds, const char **bands, int n_bands, struct scCats *scatts, const char **cats_rasts)
Compute scatter plots data.
int I_merge_arrays(unsigned char *merged_arr, unsigned char *overlay_arr, unsigned rows, unsigned cols, double alpha)
Merge arrays according to opacity. Every pixel in array must be represented by 4 values (RGBA).
int I_rasterize(double *polygon, int pol_n_pts, unsigned char val, struct Cell_head *rast_region, unsigned char *rast)
Wrapper for using of iclass perimeter rasterization by scatter plot. Warning: calls Rast_set_window.
int I_insert_patch_to_cat_rast(const char *patch_rast, struct Cell_head *cat_rast_region, const char *cat_rast)
Insert raster map patch into pgm file.
#define CELL_TYPE
Definition raster.h:11
int RASTER_MAP_TYPE
Definition raster.h:25
2D/3D raster map header (used also for region)
Definition gis.h:446
double ew_res
Resolution - east to west cell size for 2D data.
Definition gis.h:482
double north
Extent coordinates (north)
Definition gis.h:492
double east
Extent coordinates (east)
Definition gis.h:496
double ns_res
Resolution - north to south cell size for 2D data.
Definition gis.h:486
int rows
Number of rows for 2D data.
Definition gis.h:461
int cols
Number of columns for 2D data.
Definition gis.h:465
double south
Extent coordinates (south)
Definition gis.h:494
double west
Extent coordinates (west)
Definition gis.h:498
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
struct scScatts ** cats_arr
Definition imagery.h:159
int n_a_cats
Definition imagery.h:153