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