1 /*!
2    \file lib/imagery/iscatt_structs.c
3 
4    \brief Imagery library - functions for manipulation with structures used
5           by wx.iscatt (wx Interactive Scatter Plot Tool)
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 Landa)
13  */
14 #include <math.h>
15 
16 #include <grass/imagery.h>
17 #include <grass/gis.h>
18 
19 /*!
20    \brief Compute band ids from scatter plot id.
21 
22    Scatter plot id describes which bands defines the scatter plot.
23 
24    Let say we have 3 bands, their ids are 0, 1 and 2.
25    Scatter plot with id 0 consists of band 1 (b_1_id) 0 and  band 2 (b_2_id) 1.
26    All scatter plots:
27    scatt_id b_1_id b_2_id
28    0        0      1
29    1        0      2
30    2        1      2
31 
32    \param scatt_id scatter plot id
33    \param n_bands number of bands
34    \param[out] b_1_id id of band1
35    \param[out] b_2_id id of band2
36 
37    \return 0
38  */
I_id_scatt_to_bands(const int scatt_id,const int n_bands,int * b_1_id,int * b_2_id)39 int I_id_scatt_to_bands(const int scatt_id, const int n_bands, int *b_1_id,
40 			int *b_2_id)
41 {
42     int n_b1 = n_bands - 1;
43 
44     *b_1_id =
45 	(int)((2 * n_b1 + 1 -
46 	       sqrt((double)((2 * n_b1 + 1) * (2 * n_b1 + 1) - 8 * scatt_id)))
47 	      / 2);
48 
49     *b_2_id =
50 	scatt_id - ((*b_1_id) * (2 * n_b1 + 1) - (*b_1_id) * (*b_1_id)) / 2 +
51 	(*b_1_id) + 1;
52 
53     return 0;
54 }
55 
56 
57 /*!
58    \brief Compute scatter plot id from band ids.
59 
60    See also I_id_scatt_to_bands
61 
62    \param b_1_id id of band1
63    \param b_1_id id of band2
64    \param n_bands number of bands
65    \param[out] scatt_id scatter plot id
66 
67    \return 0
68  */
I_bands_to_id_scatt(const int b_1_id,const int b_2_id,const int n_bands,int * scatt_id)69 int I_bands_to_id_scatt(const int b_1_id, const int b_2_id, const int n_bands,
70 			int *scatt_id)
71 {
72     int n_b1 = n_bands - 1;
73 
74     *scatt_id =
75 	(b_1_id * (2 * n_b1 + 1) - b_1_id * b_1_id) / 2 + b_2_id - b_1_id - 1;
76 
77     return 0;
78 }
79 
80 /*!
81    \brief Initialize structure for storing scatter plots data.
82 
83    \param cats pointer to scCats struct
84    \param n_bands number of bands
85    \param type SC_SCATT_DATA - stores scatter plots
86    \param type SC_SCATT_CONDITIONS - stores selected areas in scatter plots
87  */
I_sc_init_cats(struct scCats * cats,int n_bands,int type)88 void I_sc_init_cats(struct scCats *cats, int n_bands, int type)
89 {
90     int i_cat;
91 
92     cats->type = type;
93 
94     cats->n_cats = 100;
95     cats->n_a_cats = 0;
96 
97     cats->n_bands = n_bands;
98     cats->n_scatts = (n_bands - 1) * n_bands / 2;
99 
100     cats->cats_arr =
101 	(struct scScatts **)G_malloc(cats->n_cats *
102 				     sizeof(struct scScatts *));
103     G_zero(cats->cats_arr, cats->n_cats * sizeof(struct scScatts *));
104 
105     cats->cats_ids = (int *)G_malloc(cats->n_cats * sizeof(int));
106     cats->cats_idxs = (int *)G_malloc(cats->n_cats * sizeof(int));
107 
108     for (i_cat = 0; i_cat < cats->n_cats; i_cat++)
109 	cats->cats_idxs[i_cat] = -1;
110 
111     return;
112 }
113 
114 /*!
115    \brief Free data of struct scCats, the structure itself remains allocated.
116 
117    \param cats pointer to existing scCats struct
118  */
I_sc_free_cats(struct scCats * cats)119 void I_sc_free_cats(struct scCats *cats)
120 {
121     int i_cat;
122 
123     for (i_cat = 0; i_cat < cats->n_a_cats; i_cat++) {
124 	if (cats->cats_arr[i_cat]) {
125 	    G_free(cats->cats_arr[i_cat]->scatt_idxs);
126 	    G_free(cats->cats_arr[i_cat]->scatts_bands);
127 	    G_free(cats->cats_arr[i_cat]->scatts_arr);
128 	    G_free(cats->cats_arr[i_cat]);
129 	}
130     }
131 
132     G_free(cats->cats_ids);
133     G_free(cats->cats_idxs);
134     G_free(cats->cats_arr);
135 
136     cats->n_cats = 0;
137     cats->n_a_cats = 0;
138     cats->n_bands = 0;
139     cats->n_scatts = 0;
140     cats->type = -1;
141 
142     return;
143 }
144 
145 /*!
146    \brief Add category.
147 
148    Category represents group of scatter plots.
149 
150    \param cats pointer to scCats struct
151 
152    \return assigned category id (starts with 0)
153    \return -1 if maximum nuber of categories was reached
154  */
I_sc_add_cat(struct scCats * cats)155 int I_sc_add_cat(struct scCats *cats)
156 {
157     int i_scatt, i_cat_id, cat_id;
158     int n_a_cats = cats->n_a_cats;
159 
160     if (cats->n_a_cats >= cats->n_cats)
161 	return -1;
162 
163     for (i_cat_id = 0; i_cat_id < cats->n_cats; i_cat_id++)
164 	if (cats->cats_idxs[i_cat_id] < 0) {
165 	    cat_id = i_cat_id;
166 	    break;
167 	}
168 
169     cats->cats_ids[n_a_cats] = cat_id;
170     cats->cats_idxs[cat_id] = n_a_cats;
171 
172     cats->cats_arr[n_a_cats] =
173 	(struct scScatts *)G_malloc(sizeof(struct scScatts));
174 
175     cats->cats_arr[n_a_cats]->scatts_arr =
176 	(struct scdScattData **)G_malloc(cats->n_scatts *
177 					 sizeof(struct scdScattData *));
178     G_zero((cats->cats_arr[n_a_cats]->scatts_arr),
179 	   cats->n_scatts * sizeof(struct scdScattData *));
180 
181     cats->cats_arr[n_a_cats]->n_a_scatts = 0;
182 
183     cats->cats_arr[n_a_cats]->scatts_bands =
184 	(int *)G_malloc(cats->n_scatts * 2 * sizeof(int));
185 
186     cats->cats_arr[n_a_cats]->scatt_idxs =
187 	(int *)G_malloc(cats->n_scatts * sizeof(int));
188     for (i_scatt = 0; i_scatt < cats->n_scatts; i_scatt++)
189 	cats->cats_arr[n_a_cats]->scatt_idxs[i_scatt] = -1;
190 
191     ++cats->n_a_cats;
192 
193     return cat_id;
194 }
195 
196 /*!
197    \brief Insert scatter plot data .
198    Inserted scatt_data struct must have same type as
199    cats struct (SC_SCATT_DATA or SC_SCATT_CONDITIONS).
200 
201    \param cats pointer to scCats struct
202    \param scarr_data pointer to scdScattData struct
203    \param cat_id id number of category
204    \param scatt_id id number of scatter plot
205 
206    \return  0 on success
207    \return -1 on failure
208  */
I_sc_insert_scatt_data(struct scCats * cats,struct scdScattData * scatt_data,int cat_id,int scatt_id)209 int I_sc_insert_scatt_data(struct scCats *cats,
210 			   struct scdScattData *scatt_data, int cat_id,
211 			   int scatt_id)
212 {
213     int band_1, band_2, cat_idx, n_a_scatts;
214     struct scScatts *scatts;
215 
216     if (cat_id < 0 || cat_id >= cats->n_cats)
217 	return -1;
218 
219     cat_idx = cats->cats_idxs[cat_id];
220     if (cat_idx < 0)
221 	return -1;
222 
223     if (scatt_id < 0 && scatt_id >= cats->n_scatts)
224 	return -1;
225 
226     scatts = cats->cats_arr[cat_idx];
227     if (scatts->scatt_idxs[scatt_id] >= 0)
228 	return -1;
229 
230     if (!scatt_data->b_conds_arr && cats->type == SC_SCATT_CONDITIONS)
231 	return -1;
232 
233     if (!scatt_data->scatt_vals_arr && cats->type == SC_SCATT_DATA)
234 	return -1;
235 
236     n_a_scatts = scatts->n_a_scatts;
237 
238     scatts->scatt_idxs[scatt_id] = n_a_scatts;
239 
240     I_id_scatt_to_bands(scatt_id, cats->n_bands, &band_1, &band_2);
241 
242     scatts->scatts_bands[n_a_scatts * 2] = band_1;
243     scatts->scatts_bands[n_a_scatts * 2 + 1] = band_2;
244 
245     scatts->scatts_arr[n_a_scatts] = scatt_data;
246     ++scatts->n_a_scatts;
247 
248     return 0;
249 }
250 
251 /*!
252    \brief Insert scatter plot data.
253 
254    \param scatt_data pointer to existing struct scdScattData
255    \param type SC_SCATT_DATA for scatter plots or
256                SC_SCATT_CONDITIONS for selected areas in scatter plot
257    \param n_vals number of data values
258    \param data array of values (unsigned char for SC_SCATT_CONDITIONS,
259           unsigned int for SC_SCATT_DATA)
260  */
I_scd_init_scatt_data(struct scdScattData * scatt_data,int type,int n_vals,void * data)261 void I_scd_init_scatt_data(struct scdScattData *scatt_data, int type,
262 			   int n_vals, void *data)
263 {
264     scatt_data->n_vals = n_vals;
265 
266     if (type == SC_SCATT_DATA) {
267 	if (data)
268 	    scatt_data->scatt_vals_arr = (unsigned int *)data;
269 	else {
270 	    scatt_data->scatt_vals_arr =
271 		(unsigned int *)G_malloc(n_vals * sizeof(unsigned int));
272         G_zero(scatt_data->scatt_vals_arr,
273 		   n_vals * sizeof(unsigned int));
274 	}
275 	scatt_data->b_conds_arr = NULL;
276     }
277     else if (type == SC_SCATT_CONDITIONS) {
278 	if (data)
279 	    scatt_data->b_conds_arr = (unsigned char *)data;
280 	else {
281 	    scatt_data->b_conds_arr =
282 		(unsigned char *)G_malloc(n_vals * sizeof(unsigned char));
283         G_zero(scatt_data->b_conds_arr,
284 		   n_vals * sizeof(unsigned char));
285 	}
286 	scatt_data->scatt_vals_arr = NULL;
287     }
288 
289     return;
290 }
291