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