[GRASS-SVN] r57846 - in grass/trunk: include include/defs lib/imagery
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Sep 26 13:32:19 PDT 2013
Author: turek
Date: 2013-09-26 13:32:19 -0700 (Thu, 26 Sep 2013)
New Revision: 57846
Added:
grass/trunk/lib/imagery/iscatt_core.c
grass/trunk/lib/imagery/iscatt_structs.c
Modified:
grass/trunk/include/defs/imagery.h
grass/trunk/include/imagery.h
Log:
wx.iscatt: c backend
Modified: grass/trunk/include/defs/imagery.h
===================================================================
--- grass/trunk/include/defs/imagery.h 2013-09-26 18:39:38 UTC (rev 57845)
+++ grass/trunk/include/defs/imagery.h 2013-09-26 20:32:19 UTC (rev 57846)
@@ -111,6 +111,28 @@
FILE *I_fopen_subgroup_ref_new(const char *, const char *);
FILE *I_fopen_subgroup_ref_old(const char *, const char *);
+/* iscatt_structs.c */
+void I_sc_init_cats(struct scCats *, int, int);
+void I_sc_free_cats(struct scCats *);
+int I_sc_add_cat(struct scCats *);
+int I_sc_insert_scatt_data(struct scCats *, struct scdScattData *, int, int);
+
+void I_scd_init_scatt_data(struct scdScattData *, int, int, void *);
+
+/* iscatt_core.c */
+int I_compute_scatts(struct Cell_head *, struct scCats *, const char **,
+ const char **, int, struct scCats *, const char **);
+
+int I_create_cat_rast(struct Cell_head *, const char *);
+int I_insert_patch_to_cat_rast(const char *, struct Cell_head *, const char *);
+
+int I_id_scatt_to_bands(const int, const int, int *, int *);
+int I_bands_to_id_scatt(const int, const int, const int, int *);
+
+int I_merge_arrays(unsigned char *, unsigned char *, unsigned, unsigned, double);
+int I_apply_colormap(unsigned char *, unsigned char *, unsigned, unsigned char *, unsigned char *);
+int I_rasterize(double *, int, unsigned char, struct Cell_head *, unsigned char *);
+
/* sig.c */
int I_init_signatures(struct Signature *, int);
int I_new_signature(struct Signature *);
Modified: grass/trunk/include/imagery.h
===================================================================
--- grass/trunk/include/imagery.h 2013-09-26 18:39:38 UTC (rev 57845)
+++ grass/trunk/include/imagery.h 2013-09-26 20:32:19 UTC (rev 57846)
@@ -135,6 +135,63 @@
} IClass_statistics;
+/* wx.iscatt backend */
+
+#define SC_SCATT_DATA 0
+#define SC_SCATT_CONDITIONS 1
+
+/*! Holds list of all catagories.
+ It can contain selected areas for scatter plots (SC_SCATT_CONDITIONS type)
+ or computed scatter plots (SC_SCATT_DATA type).
+*/
+struct scCats
+{
+ int type; /*!< SC_SCATT_DATA -> computed scatter plots, SC_SCATT_CONDITIONS ->
+ set conditions for scatter plots to be computed */
+
+ int n_cats; /*!< number of alocated categories */
+
+ int n_bands; /*!< number of analyzed bands */
+ int n_scatts; /*!< number of possible scattter plots, which can be created from bands */
+
+ int n_a_cats; /*!< number of used/active categories */
+ int * cats_ids; /*!< (cat_idx->cat_id) array index is internal idx (position in cats_arr)
+ and id is saved in it's position*/
+ int * cats_idxs; /*!< (cat_id->cat_idx) array index is id and internal idx is saved
+ in it's position*/
+
+ struct scScatts ** cats_arr; /*!< array of pointers to struct scScatts */
+};
+
+
+/*! Holds list of all scatter plots, which belongs to category.
+*/
+struct scScatts
+{
+ int n_a_scatts; /*!< number of used/active scatter plots*/
+
+ int * scatts_bands; /*!< array of bands, which represents the scatter plots,
+ every scatter plot has assigned two bads
+ (size of the array is n_a_scatts * 2 -> idx*2)*/
+ int * scatt_idxs; /*!< (scatt_id->scatt_idx) internal idx of the scatter plot
+ (position in scatts_arr)*/
+
+ struct scdScattData ** scatts_arr; /*!< array of pointers to scdScattData */
+};
+
+/*! Holds scatter plot data.
+*/
+struct scdScattData
+{
+ int n_vals; /*!< Number of values in scatter plot
+ (length of b_conds_arr or scatt_vals_arr arrays). */
+
+ unsigned char * b_conds_arr; /*!< array of selected areas
+ (used for SC_SCATT_CONDITIONS type) otherwise NULL */
+ unsigned int * scatt_vals_arr; /*!< array of computed areas
+ (used for SC_SCATT_DATA type) otherwise NULL */
+};
+
#define SIGNATURE_TYPE_MIXED 1
#define GROUPFILE "CURGROUP"
Added: grass/trunk/lib/imagery/iscatt_core.c
===================================================================
--- grass/trunk/lib/imagery/iscatt_core.c (rev 0)
+++ grass/trunk/lib/imagery/iscatt_core.c 2013-09-26 20:32:19 UTC (rev 57846)
@@ -0,0 +1,1005 @@
+/*!
+ \file lib/imagery/iscatt_core.c
+
+ \brief Imagery library - wx.iscatt (wx Interactive Scatter Plot Tool) backend.
+
+ Copyright (C) 2013 by the GRASS Development Team
+
+ This program is free software under the GNU General Public License
+ (>=v2). Read the file COPYING that comes with GRASS for details.
+
+ \author Stepan Turek <stepan.turek at seznam.cz> (GSoC 2013, Mentor: Martin Landa)
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grass/gis.h>
+#include <grass/vector.h>
+#include <grass/raster.h>
+#include <grass/imagery.h>
+#include <grass/glocale.h>
+
+#include "iclass_local_proto.h"
+
+struct rast_row
+{
+ CELL *row;
+ char *null_row;
+ struct Range rast_range; /*Range of whole raster. */
+};
+
+/*!
+ \brief Create pgm header.
+
+ Scatter plot internally generates pgm files.
+ These pgms have header in format created by this function.
+
+ \param region region to be pgm header generated for
+ \param [out] header header of pgm file
+ */
+static int get_cat_rast_header(struct Cell_head *region, char *header)
+{
+ return sprintf(header, "P5\n%d\n%d\n1\n", region->cols, region->rows);
+}
+
+/*!
+ \brief Create category raster conditions file.
+ The file is used for holding selected areas from mapwindow.
+ The reason why the standard GRASS raster is not used is that for every
+ modification (new area is selected) we would need to create whole new raster.
+ Instead of this scatter plot only modifies affected region in
+ the internal pgm file.
+
+ \param cat_rast_region region to be file generated for
+ \param[out] cat_rast path where the pgm raster file will be generated
+ */
+int I_create_cat_rast(struct Cell_head *cat_rast_region, const char *cat_rast)
+{
+ FILE *f_cat_rast;
+ char cat_rast_header[1024]; //TODO magic number
+ int i_row, i_col;
+ int head_nchars;
+
+ unsigned char *row_data;
+
+ f_cat_rast = fopen(cat_rast, "wb");
+ if (!f_cat_rast) {
+ G_warning("Unable to create category raster condition file <%s>.",
+ cat_rast);
+ return -1;
+ }
+
+ head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
+
+ fwrite(cat_rast_header, sizeof(char), head_nchars / sizeof(char),
+ f_cat_rast);
+ if (ferror(f_cat_rast)) {
+ fclose(f_cat_rast);
+ G_warning(_
+ ("Unable to write header into category raster condition file <%s>."),
+ cat_rast);
+ return -1;
+ }
+
+ row_data =
+ (unsigned char *)G_malloc(cat_rast_region->cols *
+ sizeof(unsigned char));
+ for (i_col = 0; i_col < cat_rast_region->cols; i_col++)
+ row_data[i_col] = 0 & 255;
+
+ for (i_row = 0; i_row < cat_rast_region->rows; i_row++) {
+ fwrite(row_data, sizeof(unsigned char),
+ (cat_rast_region->cols) / sizeof(unsigned char), f_cat_rast);
+ if (ferror(f_cat_rast)) {
+ fclose(f_cat_rast);
+ G_warning(_
+ ("Unable to write into category raster condition file <%s>."),
+ cat_rast);
+ return -1;
+ }
+ }
+
+ fclose(f_cat_rast);
+ return 0;
+}
+
+/*!
+ \brief Find intersection region of two regions.
+
+ \param A pointer to intersected region
+ \param B pointer to intersected region
+ \param [out] intersec pointer to intersection region of regions A B
+ (relevant params of the region are: south, north, east, west)
+
+ \return 0 if interection exists
+ \return -1 if regions does not intersect
+ */
+static int regions_intersecion(struct Cell_head *A, struct Cell_head *B,
+ struct Cell_head *intersec)
+{
+
+ if (B->north < A->south)
+ return -1;
+ else if (B->north > A->north)
+ intersec->north = A->north;
+ else
+ intersec->north = B->north;
+
+ if (B->south > A->north)
+ return -1;
+ else if (B->south < A->south)
+ intersec->south = A->south;
+ else
+ intersec->south = B->south;
+
+ if (B->east < A->west)
+ return -1;
+ else if (B->east > A->east)
+ intersec->east = A->east;
+ else
+ intersec->east = B->east;
+
+ if (B->west > A->east)
+ return -1;
+ else if (B->west < A->west)
+ intersec->west = A->west;
+ else
+ intersec->west = B->west;
+
+ if (intersec->north == intersec->south)
+ return -1;
+
+ if (intersec->east == intersec->west)
+ return -1;
+
+ return 0;
+
+}
+
+/*!
+ \brief Get rows and cols numbers, which defines intersection of the regions.
+
+ \param A pointer to intersected region
+ \param B pointer to intersected region (A and B must have same resolution)
+ \param [out] A_bounds rows and cols numbers of A stored in
+ south, north, east, west, which defines intersection of A and B
+ \param [out] B_bounds rows and cols numbers of B stored in
+ south, north, east, west, which defines intersection of A and B
+
+ \return 0 if interection exists
+ \return -1 if regions do not intersect
+ \return -2 resolution of regions is not same
+ */
+static int get_rows_and_cols_bounds(struct Cell_head *A, struct Cell_head *B,
+ struct Cell_head *A_bounds,
+ struct Cell_head *B_bounds)
+{
+ float ns_res, ew_res;
+
+ struct Cell_head intersec;
+
+ /* TODO is it right check? */
+ if (abs(A->ns_res - B->ns_res) > GRASS_EPSILON) {
+ G_warning(
+ "'get_rows_and_cols_bounds' ns_res does not fit, A->ns_res: %f B->ns_res: %f",
+ A->ns_res, B->ns_res);
+ return -2;
+ }
+
+ if (abs(A->ew_res - B->ew_res) > GRASS_EPSILON) {
+ G_warning(
+ "'get_rows_and_cols_bounds' ew_res does not fit, A->ew_res: %f B->ew_res: %f",
+ A->ew_res, B->ew_res);
+ return -2;
+ }
+
+ ns_res = A->ns_res;
+ ew_res = A->ew_res;
+
+ if (regions_intersecion(A, B, &intersec) == -1)
+ return -1;
+
+ A_bounds->north =
+ ceil((A->north - intersec.north - ns_res * 0.5) / ns_res);
+ A_bounds->south =
+ ceil((A->north - intersec.south - ns_res * 0.5) / ns_res);
+
+ A_bounds->east = ceil((intersec.east - A->west - ew_res * 0.5) / ew_res);
+ A_bounds->west = ceil((intersec.west - A->west - ew_res * 0.5) / ew_res);
+
+ B_bounds->north =
+ ceil((B->north - intersec.north - ns_res * 0.5) / ns_res);
+ B_bounds->south =
+ ceil((B->north - intersec.south - ns_res * 0.5) / ns_res);
+
+ B_bounds->east = ceil((intersec.east - B->west - ew_res * 0.5) / ew_res);
+ B_bounds->west = ceil((intersec.west - B->west - ew_res * 0.5) / ew_res);
+
+ return 0;
+}
+
+/*!
+ \brief Insert raster map patch into pgm file.
+ \see I_create_cat_rast
+
+ Warning: calls Rast_set_window
+
+ \param patch_rast name of raster map
+ \param cat_rast_region region of category raster file
+ \param cat_rast path to category raster file
+
+ \return 0 on success
+ \return -1 on failure
+ */
+int I_insert_patch_to_cat_rast(const char *patch_rast,
+ struct Cell_head *cat_rast_region,
+ const char *cat_rast)
+{
+
+ FILE *f_cat_rast;
+ struct Cell_head patch_region, patch_bounds, cat_rast_bounds;
+ char cat_rast_header[1024];
+ int i_row, i_col, ncols, nrows, patch_col;
+ int head_nchars, ret;
+ int fd_patch_rast, init_shift, step_shift;
+ unsigned char *patch_data;
+
+ char *null_chunk_row;
+
+ const char *mapset;
+
+ f_cat_rast = fopen(cat_rast, "rb+");
+ if (!f_cat_rast) {
+ G_warning(_("Unable to open category raster condtions file <%s>."),
+ cat_rast);
+ return -1;
+ }
+
+ head_nchars = get_cat_rast_header(cat_rast_region, cat_rast_header);
+ if ((mapset = G_find_raster((char *)patch_rast, "")) == NULL) {
+ fclose(f_cat_rast);
+ G_warning(_("Unable to find patch raster <%s>."), patch_rast);
+ return -1;
+ }
+
+ Rast_get_cellhd(patch_rast, mapset, &patch_region);
+ Rast_set_window(&patch_region);
+
+ if ((fd_patch_rast = Rast_open_old(patch_rast, mapset)) < 0) {
+ fclose(f_cat_rast);
+ return -1;
+ }
+
+ ret =
+ get_rows_and_cols_bounds(cat_rast_region, &patch_region,
+ &cat_rast_bounds, &patch_bounds);
+ if (ret == -2) {
+ G_warning(_
+ ("Resolutions of patch <%s> and patched file <%s> are not same."),
+ patch_rast, cat_rast);
+
+ Rast_close(fd_patch_rast);
+ fclose(f_cat_rast);
+
+ return -1;
+ }
+ else if (ret == -1) {
+
+ Rast_close(fd_patch_rast);
+ fclose(f_cat_rast);
+
+ return 0;
+ }
+
+ ncols = cat_rast_bounds.east - cat_rast_bounds.west;
+ nrows = cat_rast_bounds.south - cat_rast_bounds.north;
+
+ patch_data = (unsigned char *)G_malloc(ncols * sizeof(unsigned char));
+
+ init_shift =
+ head_nchars + cat_rast_region->cols * cat_rast_bounds.north +
+ cat_rast_bounds.west;
+
+ if (fseek(f_cat_rast, init_shift, SEEK_SET) != 0) {
+ G_warning(_
+ ("Corrupted category raster conditions file <%s> (fseek failed)"),
+ cat_rast);
+
+ Rast_close(fd_patch_rast);
+ fclose(f_cat_rast);
+
+ return -1;
+ }
+
+ step_shift = cat_rast_region->cols - ncols;
+
+ null_chunk_row = Rast_allocate_null_buf();
+
+ for (i_row = 0; i_row < nrows; i_row++) {
+ Rast_get_null_value_row(fd_patch_rast, null_chunk_row,
+ i_row + patch_bounds.north);
+
+ for (i_col = 0; i_col < ncols; i_col++) {
+ patch_col = patch_bounds.west + i_col;
+
+ if (null_chunk_row[patch_col] != 1)
+ patch_data[i_col] = 1 & 255;
+ else {
+ patch_data[i_col] = 0 & 255;
+ }
+ }
+
+ fwrite(patch_data, sizeof(unsigned char),
+ (ncols) / sizeof(unsigned char), f_cat_rast);
+ if (ferror(f_cat_rast)) {
+ G_warning(_
+ ("Unable to write into category raster conditions file <%s>"),
+ cat_rast);
+
+ Rast_close(fd_patch_rast);
+ G_free(null_chunk_row);
+ fclose(f_cat_rast);
+
+ return -1;
+ }
+ if (fseek(f_cat_rast, step_shift, SEEK_CUR) != 0) {
+ G_warning(_
+ ("Corrupted category raster conditions file <%s> (fseek failed)"),
+ cat_rast);
+
+ Rast_close(fd_patch_rast);
+ G_free(null_chunk_row);
+ fclose(f_cat_rast);
+
+ return -1;
+ }
+ }
+
+ Rast_close(fd_patch_rast);
+ G_free(null_chunk_row);
+ fclose(f_cat_rast);
+ return 0;
+}
+
+/*!
+ \brief Updates scatter plots data in category by pixels which meets category conditions.
+
+ \param bands_rows data represents data describig one row from raster band
+ \param belongs_pix array which defines which pixels belongs to category
+ (1 value) and which not (0 value)
+ \param [out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
+ which are modified according to values in belongs_pix
+ (represents scatter plot category)
+ */
+static inline void update_cat_scatt_plts(struct rast_row *bands_rows,
+ unsigned short *belongs_pix,
+ struct scScatts *scatts)
+{
+ int i_scatt, array_idx, i_chunk_rows_pix, max_arr_idx;
+
+ CELL *b_1_row;
+ CELL *b_2_row;
+ char *b_1_null_row, *b_2_null_row;
+ struct rast_row b_1_rast_row, b_2_rast_row;
+
+ struct Range b_1_range, b_2_range;
+ int b_1_range_size;
+
+ int row_size = Rast_window_cols();
+
+ int *scatts_bands = scatts->scatts_bands;
+
+ for (i_scatt = 0; i_scatt < scatts->n_a_scatts; i_scatt++) {
+ b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
+ b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
+
+ b_1_row = b_1_rast_row.row;
+ b_2_row = b_2_rast_row.row;
+
+ b_1_null_row = b_1_rast_row.null_row;
+ b_2_null_row = b_2_rast_row.null_row;
+
+ b_1_range = b_1_rast_row.rast_range;
+ b_2_range = b_2_rast_row.rast_range;
+
+ b_1_range_size = b_1_range.max - b_1_range.min + 1;
+ max_arr_idx =
+ (b_1_range.max - b_1_range.min + 1) * (b_2_range.max -
+ b_2_range.min + 1);
+
+ for (i_chunk_rows_pix = 0; i_chunk_rows_pix < row_size;
+ i_chunk_rows_pix++) {
+ /* pixel does not belongs to scatter plot or has null value in one of the bands */
+ if (!belongs_pix[i_chunk_rows_pix] ||
+ b_1_null_row[i_chunk_rows_pix] == 1 ||
+ b_2_null_row[i_chunk_rows_pix] == 1)
+ continue;
+
+ /* index in scatter plot array */
+ array_idx =
+ b_1_row[i_chunk_rows_pix] - b_1_range.min +
+ (b_2_row[i_chunk_rows_pix] - b_2_range.min) * b_1_range_size;
+
+ if (array_idx < 0 || array_idx >= max_arr_idx) {
+ G_warning
+ ("Inconsistent data. Value computed for scatter plot is out of initialized range.");
+ continue;
+ }
+
+ /* increment scatter plot value */
+ ++scatts->scatts_arr[i_scatt]->scatt_vals_arr[array_idx];
+ }
+ }
+}
+
+/*!
+ \brief Computes scatter plots data from bands_rows.
+
+ \param region analysis region
+ \param scatt_conds pointer to scScatts struct of type SC_SCATT_CONDITIONS,
+ where are selected areas (condtitions) stored
+ \param f_cats_rasts_conds file which stores selected areas (conditions) from
+ mapwindow see I_create_cat_rast and I_insert_patch_to_cat_rast
+ \param bands_rows data arrays of raster rows from analyzed raster bands
+ (all data in bands_rows and belongs_pix arrays represents same region (row))
+ \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
+ where are computed scatter plots stored
+ \param[out] fd_cats_rasts array of opened raster maps,
+ which every represents all selected pixels for category
+
+ \return 0 on success
+ \return -1 on failure
+ */
+static inline int compute_scatts_from_chunk_row(struct Cell_head *region,
+ struct scCats *scatt_conds,
+ FILE ** f_cats_rasts_conds,
+ struct rast_row *bands_rows,
+ struct scCats *scatts,
+ int *fd_cats_rasts)
+{
+
+ int i_rows_pix, i_cat, i_scatt, n_pixs;
+ int cat_id, scatt_plts_cat_idx, array_idx, max_arr_idx;
+ char *b_1_null_row, *b_2_null_row;
+ struct rast_row b_1_rast_row, b_2_rast_row;
+ CELL *cat_rast_row;
+
+ struct scScatts *scatts_conds;
+ struct scScatts *scatts_scatt_plts;
+
+ struct Range b_1_range, b_2_range;
+ int b_1_range_size;
+
+ int *scatts_bands;
+
+ CELL *b_1_row;
+ CELL *b_2_row;
+ unsigned char *i_scatt_conds;
+
+ int row_size = Rast_window_cols();
+
+ unsigned short *belongs_pix =
+ (unsigned short *)G_malloc(row_size * sizeof(unsigned short));
+ unsigned char *rast_pixs =
+ (unsigned char *)G_malloc(row_size * sizeof(unsigned char));
+ cat_rast_row = Rast_allocate_c_buf();
+
+
+ for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++) {
+ scatts_conds = scatt_conds->cats_arr[i_cat];
+
+ cat_id = scatt_conds->cats_ids[i_cat];
+
+ scatt_plts_cat_idx = scatts->cats_idxs[cat_id];
+ if (scatt_plts_cat_idx < 0)
+ continue;
+ scatts_scatt_plts = scatts->cats_arr[scatt_plts_cat_idx];
+
+ G_zero(belongs_pix, row_size * sizeof(unsigned short));
+
+ /* if category has no conditions defined, scatter plots without
+ any constraint are computed (default scatter plots) */
+ if (!scatts_conds->n_a_scatts && !f_cats_rasts_conds[i_cat]) {
+ for (i_scatt = 0; i_scatt < scatts_scatt_plts->n_a_scatts;
+ i_scatt++) {
+ /* all pixels belongs */
+ for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++)
+ belongs_pix[i_rows_pix] = 1;
+ }
+ }
+ /* compute belonging pixels for defined conditions */
+ else {
+ scatts_bands = scatts_conds->scatts_bands;
+
+ /* check conditions from category raster condtitions file
+ (see I_create_cat_rast) */
+ if (f_cats_rasts_conds[i_cat]) {
+ n_pixs =
+ fread(rast_pixs, sizeof(unsigned char),
+ (row_size) / sizeof(unsigned char),
+ f_cats_rasts_conds[i_cat]);
+
+ if (ferror(f_cats_rasts_conds[i_cat])) {
+ G_free(rast_pixs);
+ G_free(belongs_pix);
+ G_warning(_
+ ("Unable to read from category raster condtition file."));
+ return -1;
+ }
+ if (n_pixs != n_pixs) {
+ G_free(rast_pixs);
+ G_free(belongs_pix);
+ G_warning(_
+ ("Invalid size of category raster conditions file."));
+ return -1;
+
+ }
+
+ for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
+ if (rast_pixs[i_rows_pix] != (0 & 255))
+ belongs_pix[i_rows_pix] = 1;
+ }
+ }
+
+ /* check condtions defined in scatter plots */
+ for (i_scatt = 0; i_scatt < scatts_conds->n_a_scatts; i_scatt++) {
+ b_1_rast_row = bands_rows[scatts_bands[i_scatt * 2]];
+ b_2_rast_row = bands_rows[scatts_bands[i_scatt * 2 + 1]];
+
+ b_1_row = b_1_rast_row.row;
+ b_2_row = b_2_rast_row.row;
+
+ b_1_null_row = b_1_rast_row.null_row;
+ b_2_null_row = b_2_rast_row.null_row;
+
+ b_1_range = b_1_rast_row.rast_range;
+ b_2_range = b_2_rast_row.rast_range;
+
+ b_1_range_size = b_1_range.max - b_1_range.min + 1;
+ max_arr_idx =
+ (b_1_range.max - b_1_range.min + 1) * (b_2_range.max -
+ b_2_range.min + 1);
+
+ i_scatt_conds =
+ scatts_conds->scatts_arr[i_scatt]->b_conds_arr;
+
+ for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++) {
+ /* pixels already belongs to category from category raster conditions
+ file or contains null value in one of the bands */
+ if (belongs_pix[i_rows_pix] ||
+ b_1_null_row[i_rows_pix] == 1 ||
+ b_2_null_row[i_rows_pix] == 1)
+ continue;
+
+ array_idx =
+ b_1_row[i_rows_pix] - b_1_range.min +
+ (b_2_row[i_rows_pix] -
+ b_2_range.min) * b_1_range_size;
+ if (array_idx < 0 || array_idx >= max_arr_idx) {
+ G_warning
+ _("Data inconsistent. "
+ "Value computed for scatter plot is out of initialized range.");
+ continue;
+ }
+ /* pixels meets condtion defined in scatter plot ->
+ belongs to scatter plot category */
+ if (i_scatt_conds[array_idx])
+ belongs_pix[i_rows_pix] = 1;
+ }
+ }
+ }
+
+ /* update category raster with belonging pixels */
+ if (fd_cats_rasts[i_cat] >= 0) {
+ Rast_set_null_value(cat_rast_row, Rast_window_cols(), CELL_TYPE);
+
+ for (i_rows_pix = 0; i_rows_pix < row_size; i_rows_pix++)
+ if (belongs_pix[i_rows_pix])
+ cat_rast_row[i_rows_pix] = belongs_pix[i_rows_pix];
+
+ Rast_put_c_row(fd_cats_rasts[i_cat], cat_rast_row);
+ }
+
+ /* update scatter plots with belonging pixels */
+ update_cat_scatt_plts(bands_rows, belongs_pix, scatts_scatt_plts);
+ }
+
+ G_free(cat_rast_row);
+ G_free(rast_pixs);
+ G_free(belongs_pix);
+
+ return 0;
+}
+
+/*!
+ \brief Get list of bands needed to be opened for analysis from scCats struct.
+ */
+static void get_needed_bands(struct scCats *cats, int *b_needed_bands)
+{
+ /* results in b_needed_bands - array of bools - if item has value 1,
+ band (defined by item index) is needed to be opened */
+ int i_cat, i_scatt;
+
+ for (i_cat = 0; i_cat < cats->n_a_cats; i_cat++) {
+ for (i_scatt = 0; i_scatt < cats->cats_arr[i_cat]->n_a_scatts;
+ i_scatt++) {
+ G_debug(3, "Active scatt %d in catt %d", i_scatt, i_cat);
+
+ b_needed_bands[cats->cats_arr[i_cat]->scatts_bands[i_scatt * 2]] =
+ 1;
+ b_needed_bands[cats->cats_arr[i_cat]->
+ scatts_bands[i_scatt * 2 + 1]] = 1;
+ }
+ }
+ return;
+}
+
+/*!
+ \brief Helper function for clean up.
+ */
+static void free_compute_scatts_data(int *fd_bands,
+ struct rast_row *bands_rows,
+ int n_a_bands, int *bands_ids,
+ int *fd_cats_rasts,
+ FILE ** f_cats_rasts_conds, int n_a_cats)
+{
+ int i, band_id;
+
+ for (i = 0; i < n_a_bands; i++) {
+ band_id = bands_ids[i];
+ if (band_id >= 0) {
+ Rast_close(fd_bands[i]);
+ G_free(bands_rows[band_id].row);
+ G_free(bands_rows[band_id].null_row);
+ }
+ }
+
+ if (f_cats_rasts_conds)
+ for (i = 0; i < n_a_cats; i++)
+ if (f_cats_rasts_conds[i])
+ fclose(f_cats_rasts_conds[i]);
+
+ if (fd_cats_rasts)
+ for (i = 0; i < n_a_cats; i++)
+ if (fd_cats_rasts[i] >= 0)
+ Rast_close(fd_cats_rasts[i]);
+
+}
+
+/*!
+ \brief Compute scatter plots data.
+
+ If category has not defined category raster condition file and no scatter plot
+ exists with condition, default/full scatter plot is computed.
+ Warning: calls Rast_set_window
+
+ \param region analysis region, beaware that all input data must be prepared for this region
+ (bands (their ranges), cats_rasts_conds rasters...)
+ \param region function calls Rast_set_window for this region
+ \param scatt_conds pointer to scScatts struct of type SC_SCATT_CONDITIONS,
+ where are stored selected areas (conditions) in scatter plots
+ \param cats_rasts_conds paths to category raster conditions files representing
+ selected areas from mapwindow (conditions) in rasters for every category
+ \param cats_rasts_conds index in array represents corresponding category id
+ \param cats_rasts_conds for manupulation with category raster conditions file
+ see also I_id_scatt_to_bands and I_insert_patch_to_cat_rast
+ \param bands names of analyzed bands, order of bands is defined by their id
+ \param n_bands number of bands
+ \param[out] scatts pointer to scScatts struct of type SC_SCATT_DATA,
+ where are computed scatter plots stored
+ \param[out] cats_rasts array of raster maps names for every category
+ where will be stored all selected pixels
+
+ \return 0 on success
+ \return -1 on failure
+ */
+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)
+{
+ const char *mapset;
+ char header[1024];
+
+ int fd_cats_rasts[scatt_conds->n_a_cats];
+ FILE *f_cats_rasts_conds[scatt_conds->n_a_cats];
+
+ struct rast_row bands_rows[n_bands];
+
+ RASTER_MAP_TYPE data_type;
+
+ int nrows, i_band, n_a_bands, band_id;
+ int i_row, head_nchars, i_cat, id_cat;
+
+ int fd_bands[n_bands];
+ int bands_ids[n_bands];
+ int b_needed_bands[n_bands];
+
+ Rast_set_window(region);
+
+ for (i_band = 0; i_band < n_bands; i_band++)
+ fd_bands[i_band] = -1;
+
+ for (i_band = 0; i_band < n_bands; i_band++)
+ bands_ids[i_band] = -1;
+
+ if (n_bands != scatts->n_bands || n_bands != scatt_conds->n_bands)
+ return -1;
+
+ G_zero(b_needed_bands, (size_t) n_bands * sizeof(int));
+
+ get_needed_bands(scatt_conds, &b_needed_bands[0]);
+ get_needed_bands(scatts, &b_needed_bands[0]);
+
+ n_a_bands = 0;
+
+ /* open band rasters, which are needed for computation */
+ for (band_id = 0; band_id < n_bands; band_id++) {
+ if (b_needed_bands[band_id]) {
+ G_debug(3, "Opening raster no. %d with name: %s", band_id,
+ bands[band_id]);
+
+ if ((mapset = G_find_raster2(bands[band_id], "")) == NULL) {
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
+ bands_ids, NULL, NULL,
+ scatt_conds->n_a_cats);
+ G_warning(_("Unbale to read find raster <%s>"),
+ bands[band_id]);
+ return -1;
+ }
+
+ if ((fd_bands[n_a_bands] =
+ Rast_open_old(bands[band_id], mapset)) < 0) {
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
+ bands_ids, NULL, NULL,
+ scatt_conds->n_a_cats);
+ G_warning(_("Unbale to open raster <%s>"), bands[band_id]);
+ return -1;
+ }
+
+ data_type = Rast_get_map_type(fd_bands[n_a_bands]);
+ if (data_type != CELL_TYPE) {
+ G_warning(_("Raster <%s> type is not <%s>"), bands[band_id],
+ "CELL");
+ return -1;
+ }
+
+ bands_rows[band_id].row = Rast_allocate_c_buf();
+ bands_rows[band_id].null_row = Rast_allocate_null_buf();
+
+ if (Rast_read_range
+ (bands[band_id], mapset,
+ &bands_rows[band_id].rast_range) != 1) {
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
+ bands_ids, NULL, NULL,
+ scatt_conds->n_a_cats);
+ G_warning(_("Unable to read range of raster <%s>"),
+ bands[band_id]);
+ return -1;
+ }
+
+ bands_ids[n_a_bands] = band_id;
+ ++n_a_bands;
+ }
+ }
+
+ /* open category rasters condition files and category rasters */
+ for (i_cat = 0; i_cat < scatts->n_a_cats; i_cat++) {
+ id_cat = scatts->cats_ids[i_cat];
+ if (cats_rasts[id_cat]) {
+ fd_cats_rasts[i_cat] =
+ Rast_open_new(cats_rasts[id_cat], CELL_TYPE);
+ }
+ else
+ fd_cats_rasts[i_cat] = -1;
+
+ if (cats_rasts_conds[id_cat]) {
+ f_cats_rasts_conds[i_cat] = fopen(cats_rasts_conds[id_cat], "r");
+ if (!f_cats_rasts_conds[i_cat]) {
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
+ bands_ids, fd_cats_rasts,
+ f_cats_rasts_conds,
+ scatt_conds->n_a_cats);
+ G_warning(_
+ ("Unable to open category raster condtition file <%s>"),
+ bands[band_id]);
+ return -1;
+ }
+ }
+ else
+ f_cats_rasts_conds[i_cat] = NULL;
+ }
+
+ head_nchars = get_cat_rast_header(region, header);
+ for (i_cat = 0; i_cat < scatt_conds->n_a_cats; i_cat++)
+ if (f_cats_rasts_conds[i_cat])
+ if (fseek(f_cats_rasts_conds[i_cat], head_nchars, SEEK_SET) != 0) {
+ G_warning(_
+ ("Corrupted category raster conditions file (fseek failed)"));
+ return -1;
+ }
+
+ nrows = Rast_window_rows();
+
+ /* analyze bands by rows */
+ for (i_row = 0; i_row < nrows; i_row++) {
+ for (i_band = 0; i_band < n_a_bands; i_band++) {
+ band_id = bands_ids[i_band];
+ Rast_get_c_row(fd_bands[i_band], bands_rows[band_id].row, i_row);
+ Rast_get_null_value_row(fd_bands[i_band],
+ bands_rows[band_id].null_row, i_row);
+ }
+ if (compute_scatts_from_chunk_row
+ (region, scatt_conds, f_cats_rasts_conds, bands_rows, scatts,
+ fd_cats_rasts) == -1) {
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands,
+ bands_ids, fd_cats_rasts,
+ f_cats_rasts_conds,
+ scatt_conds->n_a_cats);
+ return -1;
+ }
+
+ }
+ free_compute_scatts_data(fd_bands, bands_rows, n_a_bands, bands_ids,
+ fd_cats_rasts, f_cats_rasts_conds,
+ scatt_conds->n_a_cats);
+ return 0;
+}
+
+/*!
+ \brief Merge arrays according to opacity.
+ Every pixel in array must be represented by 4 values (RGBA).
+
+ Implementd for speeding up of scatter plots rendering.
+
+ \param merged_arr array which will be overlayd with overlay_arr
+ \param overlay_arr array to be merged_arr overlayed with
+ \param rows number of rows for the both arrays
+ \param cols number of columns for the both arrays
+ \param alpha transparency (0-1) of the overlay array for merging
+
+ \return 0
+ */
+int I_merge_arrays(unsigned char *merged_arr, unsigned char *overlay_arr,
+ unsigned rows, unsigned cols, double alpha)
+{
+ unsigned int i_row, i_col, i_b;
+ unsigned int row_idx, col_idx, idx;
+ unsigned int c_a_i, c_a;
+
+ for (i_row = 0; i_row < rows; i_row++) {
+ row_idx = i_row * cols;
+ for (i_col = 0; i_col < cols; i_col++) {
+ col_idx = 4 * (row_idx + i_col);
+ idx = col_idx + 3;
+
+ c_a = overlay_arr[idx] * alpha;
+ c_a_i = 255 - c_a;
+
+ merged_arr[idx] =
+ (c_a_i * (int)merged_arr[idx] + c_a * 255) / 255;
+
+ for (i_b = 0; i_b < 3; i_b++) {
+ idx = col_idx + i_b;
+ merged_arr[idx] =
+ (c_a_i * (int)merged_arr[idx] +
+ c_a * (int)overlay_arr[idx]) / 255;
+ }
+ }
+ }
+ return 0;
+}
+
+/*!
+ \brief Apply colromap to the raster.
+
+ Implementd for speeding up of scatter plots rendering.
+
+ \param vals array of values for applying the colormap
+ \param vals_mask maks of vals array
+ \param nvals number of items of vals_mask and vals array
+ \param colmap colour map to be applied
+ \param[out] col_vals output raster with applied color map (length is 4 * nvals (RGBA))
+
+ \return 0
+ */
+int I_apply_colormap(unsigned char *vals, unsigned char *vals_mask,
+ unsigned nvals, unsigned char *colmap,
+ unsigned char *col_vals)
+{
+ unsigned int i_val;
+ int v, i, i_cm;
+
+ for (i_val = 0; i_val < nvals; i_val++) {
+ i_cm = 4 * i_val;
+
+ v = vals[i_val];
+
+ if (vals_mask && vals_mask[i_val])
+ for (i = 0; i < 4; i++)
+ col_vals[i_cm + i] = colmap[258 * 4 + i];
+ else if (v > 255)
+ for (i = 0; i < 4; i++)
+ col_vals[i_cm + i] = colmap[257 * 4 + i];
+ else if (v < 0)
+ for (i = 0; i < 4; i++)
+ col_vals[i_cm + i] = colmap[256 * 4 + i];
+ else
+ for (i = 0; i < 4; i++) {
+ col_vals[i_cm + i] = colmap[v * 4 + i];
+ }
+ }
+ return 0;
+}
+
+/*!
+ \brief Wrapper for using of iclass perimeter rasterization by scatter plot.
+ Warning: calls Rast_set_window
+
+ \param polygon array of polygon coordinates [x, y, x, y...]
+ \param pol_n_pts number of points in the polygon array
+ \param val value to be assigned to cells, which belong to plygon
+ \param rast_region region of raster
+ \param[out] rast raster to be pologyn rasterized in
+
+ \return 0 on success
+ \return 1 on failure
+ */
+
+int I_rasterize(double *polygon, int pol_n_pts, unsigned char val,
+ struct Cell_head *rast_region, unsigned char *rast)
+{
+ int i;
+ int x0, x1, y;
+ int row, row_idx, i_col;
+
+ IClass_perimeter perimeter;
+
+ struct line_pnts *pol;
+
+ pol = Vect_new_line_struct();
+
+ for (i = 0; i < pol_n_pts; i++) {
+ Vect_append_point(pol, polygon[i * 2], polygon[i * 2 + 1], 0.0);
+ }
+
+ Rast_set_window(rast_region);
+
+ make_perimeter(pol, &perimeter, rast_region);
+ for (i = 1; i < perimeter.npoints; i += 2) {
+ y = perimeter.points[i].y;
+ if (y != perimeter.points[i - 1].y) {
+ G_warning(_
+ ("prepare_signature: scan line %d has odd number of points."),
+ (i + 1) / 2);
+ return 1;
+ }
+
+ x0 = perimeter.points[i - 1].x;
+ x1 = perimeter.points[i].x;
+
+ if (x0 > x1) {
+ G_warning(_("signature: perimeter points out of order."));
+ return 1;
+ }
+
+ row = (rast_region->rows - y);
+ if (row < 0 || row >= rast_region->rows) {
+ continue;
+ }
+
+ row_idx = rast_region->cols * row;
+
+ for (i_col = x0; i_col <= x1; i_col++) {
+ if (i_col < 0 || i_col >= rast_region->cols) {
+ continue;
+ }
+ rast[row_idx + i_col] = val;
+ }
+ }
+
+ Vect_destroy_line_struct(pol);
+ G_free(perimeter.points);
+ return 0;
+}
Property changes on: grass/trunk/lib/imagery/iscatt_core.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
Added: grass/trunk/lib/imagery/iscatt_structs.c
===================================================================
--- grass/trunk/lib/imagery/iscatt_structs.c (rev 0)
+++ grass/trunk/lib/imagery/iscatt_structs.c 2013-09-26 20:32:19 UTC (rev 57846)
@@ -0,0 +1,290 @@
+/*!
+ \file lib/imagery/iscatt_structs.c
+
+ \brief Imagery library - functions for manipulation with structures used
+ by wx.iscatt (wx Interactive Scatter Plot Tool)
+
+ Copyright (C) 2013 by the GRASS Development Team
+
+ This program is free software under the GNU General Public License
+ (>=v2). Read the file COPYING that comes with GRASS for details.
+
+ \author Stepan Turek <stepan.turek at seznam.cz> (GSoC 2013, Mentor: Martin Landa)
+ */
+#include <math.h>
+
+#include <grass/imagery.h>
+#include <grass/gis.h>
+
+/*!
+ \brief Compute band ids from scatter plot id.
+
+ Scatter plot id describes which bands defines the scatter plot.
+
+ Let say we have 3 bands, their ids are 0, 1 and 2.
+ Scatter plot with id 0 consists of band 1 (b_1_id) 0 and band 2 (b_2_id) 1.
+ All scatter plots:
+ scatt_id b_1_id b_2_id
+ 0 0 1
+ 1 0 2
+ 2 1 2
+
+ \param scatt_id scatter plot id
+ \param n_bands number of bands
+ \param[out] b_1_id id of band1
+ \param[out] b_2_id id of band2
+
+ \return 0
+ */
+int I_id_scatt_to_bands(const int scatt_id, const int n_bands, int *b_1_id,
+ int *b_2_id)
+{
+ int n_b1 = n_bands - 1;
+
+ *b_1_id =
+ (int)((2 * n_b1 + 1 -
+ sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id)))
+ / 2);
+
+ *b_2_id =
+ scatt_id - ((*b_1_id) * (2 * n_b1 + 1) - (*b_1_id) * (*b_1_id)) / 2 +
+ (*b_1_id) + 1;
+
+ return 0;
+}
+
+
+/*!
+ \brief Compute scatter plot id from band ids.
+
+ See also I_id_scatt_to_bands
+
+ \param b_1_id id of band1
+ \param b_1_id id of band2
+ \param n_bands number of bands
+ \param[out] scatt_id scatter plot id
+
+ \return 0
+ */
+int I_bands_to_id_scatt(const int b_1_id, const int b_2_id, const int n_bands,
+ int *scatt_id)
+{
+ int n_b1 = n_bands - 1;
+
+ *scatt_id =
+ (b_1_id * (2 * n_b1 + 1) - b_1_id * b_1_id) / 2 + b_2_id - b_1_id - 1;
+
+ return 0;
+}
+
+/*!
+ \brief Initialize structure for storing scatter plots data.
+
+ \param cats pointer to scCats struct
+ \param n_bands number of bands
+ \param type SC_SCATT_DATA - stores scatter plots
+ \param type SC_SCATT_CONDITIONS - stores selected areas in scatter plots
+ */
+void I_sc_init_cats(struct scCats *cats, int n_bands, int type)
+{
+ int i_cat;
+
+ cats->type = type;
+
+ cats->n_cats = 100;
+ cats->n_a_cats = 0;
+
+ cats->n_bands = n_bands;
+ cats->n_scatts = (n_bands - 1) * n_bands / 2;
+
+ cats->cats_arr =
+ (struct scScatts **)G_malloc(cats->n_cats *
+ sizeof(struct scScatts *));
+ G_zero(cats->cats_arr, cats->n_cats * sizeof(struct scScatts *));
+
+ cats->cats_ids = (int *)G_malloc(cats->n_cats * sizeof(int));
+ cats->cats_idxs = (int *)G_malloc(cats->n_cats * sizeof(int));
+
+ for (i_cat = 0; i_cat < cats->n_cats; i_cat++)
+ cats->cats_idxs[i_cat] = -1;
+
+ return;
+}
+
+/*!
+ \brief Free data of struct scCats, the structure itself remains alocated.
+
+ \param cats pointer to existing scCats struct
+ */
+void I_sc_free_cats(struct scCats *cats)
+{
+ int i_cat;
+
+ for (i_cat = 0; i_cat < cats->n_a_cats; i_cat++) {
+ if (cats->cats_arr[i_cat]) {
+ G_free(cats->cats_arr[i_cat]->scatt_idxs);
+ G_free(cats->cats_arr[i_cat]->scatts_bands);
+ G_free(cats->cats_arr[i_cat]->scatts_arr);
+ G_free(cats->cats_arr[i_cat]);
+ }
+ }
+
+ G_free(cats->cats_ids);
+ G_free(cats->cats_idxs);
+ G_free(cats->cats_arr);
+
+ cats->n_cats = 0;
+ cats->n_a_cats = 0;
+ cats->n_bands = 0;
+ cats->n_scatts = 0;
+ cats->type = -1;
+
+ return;
+}
+
+/*!
+ \brief Add category.
+
+ Category represents group of scatter plots.
+
+ \param cats pointer to scCats struct
+
+ \return assigned category id (starts with 0)
+ \return -1 if maximum nuber of categories was reached
+ */
+int I_sc_add_cat(struct scCats *cats)
+{
+ int i_scatt, i_cat_id, cat_id;
+ int n_a_cats = cats->n_a_cats;
+
+ if (cats->n_a_cats >= cats->n_cats)
+ return -1;
+
+ for (i_cat_id = 0; i_cat_id < cats->n_cats; i_cat_id++)
+ if (cats->cats_idxs[i_cat_id] < 0) {
+ cat_id = i_cat_id;
+ break;
+ }
+
+ cats->cats_ids[n_a_cats] = cat_id;
+ cats->cats_idxs[cat_id] = n_a_cats;
+
+ cats->cats_arr[n_a_cats] =
+ (struct scScatts *)G_malloc(sizeof(struct scScatts));
+
+ cats->cats_arr[n_a_cats]->scatts_arr =
+ (struct scdScattData **)G_malloc(cats->n_scatts *
+ sizeof(struct scdScattData *));
+ G_zero((cats->cats_arr[n_a_cats]->scatts_arr),
+ cats->n_scatts * sizeof(struct scdScattData *));
+
+ cats->cats_arr[n_a_cats]->n_a_scatts = 0;
+
+ cats->cats_arr[n_a_cats]->scatts_bands =
+ (int *)G_malloc(cats->n_scatts * 2 * sizeof(int));
+
+ cats->cats_arr[n_a_cats]->scatt_idxs =
+ (int *)G_malloc(cats->n_scatts * sizeof(int));
+ for (i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
+ cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
+
+ ++cats->n_a_cats;
+
+ return cat_id;
+}
+
+/*!
+ \brief Insert scatter plot data .
+ Inserted scatt_data struct must have same type as
+ cats struct (SC_SCATT_DATA or SC_SCATT_CONDITIONS).
+
+ \param cats pointer to scCats struct
+ \param scarr_data pointer to scdScattData struct
+ \param cat_id id number of category
+ \param scatt_id id number of scatter plot
+
+ \return 0 on success
+ \return -1 on failure
+ */
+int I_sc_insert_scatt_data(struct scCats *cats,
+ struct scdScattData *scatt_data, int cat_id,
+ int scatt_id)
+{
+ int band_1, band_2, cat_idx, n_a_scatts;
+ struct scScatts *scatts;
+
+ if (cat_id < 0 || cat_id >= cats->n_cats)
+ return -1;
+
+ cat_idx = cats->cats_idxs[cat_id];
+ if (cat_idx < 0)
+ return -1;
+
+ if (scatt_id < 0 && scatt_id >= cats->n_scatts)
+ return -1;
+
+ scatts = cats->cats_arr[cat_idx];
+ if (scatts->scatt_idxs[scatt_id] >= 0)
+ return -1;
+
+ if (!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
+ return -1;
+
+ if (!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
+ return -1;
+
+ n_a_scatts = scatts->n_a_scatts;
+
+ scatts->scatt_idxs[scatt_id] = n_a_scatts;
+
+ I_id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
+
+ scatts->scatts_bands[n_a_scatts * 2] = band_1;
+ scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
+
+ scatts->scatts_arr[n_a_scatts] = scatt_data;
+ ++scatts->n_a_scatts;
+
+ return 0;
+}
+
+/*!
+ \brief Insert scatter plot data.
+
+ \param scatt_data pointer to existing struct scdScattData
+ \param type SC_SCATT_DATA for scatter plots or
+ SC_SCATT_CONDITIONS for selected areas in scatter plot
+ \param n_vals number of data values
+ \param data array of values (unsigned char for SC_SCATT_CONDITIONS,
+ unsigned int for SC_SCATT_DATA)
+ */
+void I_scd_init_scatt_data(struct scdScattData *scatt_data, int type,
+ int n_vals, void *data)
+{
+ scatt_data->n_vals = n_vals;
+
+ if (type == SC_SCATT_DATA) {
+ if (data)
+ scatt_data->scatt_vals_arr = (unsigned int *)data;
+ else {
+ scatt_data->scatt_vals_arr =
+ (unsigned int *)G_malloc(n_vals * sizeof(unsigned int));
+ G_zero(scatt_data->scatt_vals_arr,
+ n_vals * sizeof(unsigned int));
+ }
+ scatt_data->b_conds_arr = NULL;
+ }
+ else if (type == SC_SCATT_CONDITIONS) {
+ if (data)
+ scatt_data->b_conds_arr = (unsigned char *)data;
+ else {
+ scatt_data->b_conds_arr =
+ (unsigned char *)G_malloc(n_vals * sizeof(unsigned char));
+ G_zero(scatt_data->b_conds_arr,
+ n_vals * sizeof(unsigned char));
+ }
+ scatt_data->scatt_vals_arr = NULL;
+ }
+
+ return;
+}
Property changes on: grass/trunk/lib/imagery/iscatt_structs.c
___________________________________________________________________
Added: svn:mime-type
+ text/x-csrc
Added: svn:eol-style
+ native
More information about the grass-commit
mailing list