GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
dataquad.c
Go to the documentation of this file.
1/*!
2 * \file qtree.c
3 *
4 * \author
5 * H. Mitasova, I. Kosinovsky, D. Gerdes, Fall 1993,
6 * University of Illinois and
7 * US Army Construction Engineering Research Lab
8 *
9 * \author H. Mitasova (University of Illinois),
10 * \author I. Kosinovsky, (USA-CERL)
11 * \author D.Gerdes (USA-CERL)
12 *
13 * \author modified by H. Mitasova, November 1996 (include variable smoothing)
14 *
15 * SPDX-FileCopyrightText: 1993-1996 Helena Mitasova
16 * SPDX-FileCopyrightText: GRASS Development Team
17 * SPDX-License-Identifier: GPL-2.0-or-later
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <grass/dataquad.h>
23
24/*!
25 * Initialize point structure with given arguments
26 *
27 * This is a constructor of the point structure and it allocates memory.
28 *
29 * \note
30 * Smoothing is part of the point structure
31 */
32struct triple *quad_point_new(double x, double y, double z, double sm)
33{
34 struct triple *point;
35
36 if (!(point = (struct triple *)malloc(sizeof(struct triple)))) {
37 return NULL;
38 }
39
40 point->x = x;
41 point->y = y;
42 point->z = z;
43 point->sm = sm;
44
45 return point;
46}
47
48/*!
49 * Initialize quaddata structure with given arguments
50 *
51 * This is a constructor of the quaddata structure and it allocates memory.
52 * It also creates (and allocates memory for) the given number of points
53 * (given by *kmax*). The point attributes are set to zero.
54 */
55struct quaddata *quad_data_new(double x_or, double y_or, double xmax,
56 double ymax, int rows, int cols, int n_points,
57 int kmax)
58{
59 struct quaddata *data;
60 int i;
61
62 if (!(data = (struct quaddata *)malloc(sizeof(struct quaddata)))) {
63 return NULL;
64 }
65
66 data->x_orig = x_or;
67 data->y_orig = y_or;
68 data->xmax = xmax;
69 data->ymax = ymax;
70 data->n_rows = rows;
71 data->n_cols = cols;
72 data->n_points = n_points;
73 data->points = (struct triple *)malloc(sizeof(struct triple) * (kmax + 1));
74 if (!data->points) {
75 free(data);
76 return NULL;
77 }
78 for (i = 0; i <= kmax; i++) {
79 data->points[i].x = 0.;
80 data->points[i].y = 0.;
81 data->points[i].z = 0.;
82 data->points[i].sm = 0.;
83 }
84
85 return data;
86}
87
88/*!
89 * Return the quadrant the point should be inserted in
90 */
91int quad_compare(struct triple *point, struct quaddata *data)
92{
93 int cond1, cond2, cond3, cond4, rows, cols;
94 double ew_res, ns_res;
95
96 if (data == NULL)
97 return -1;
98
99 ew_res = (data->xmax - data->x_orig) / data->n_cols;
100 ns_res = (data->ymax - data->y_orig) / data->n_rows;
101
102 if (data->n_rows % 2 == 0) {
103 rows = data->n_rows / 2;
104 }
105 else {
106 rows = (int)(data->n_rows / 2) + 1;
107 }
108
109 if (data->n_cols % 2 == 0) {
110 cols = data->n_cols / 2;
111 }
112 else {
113 cols = (int)(data->n_cols / 2) + 1;
114 }
115 cond1 = (point->x >= data->x_orig);
116 cond2 = (point->x >= data->x_orig + ew_res * cols);
117 cond3 = (point->y >= data->y_orig);
118 cond4 = (point->y >= data->y_orig + ns_res * rows);
119 if (cond1 && cond3) {
120 if (cond2 && cond4)
121 return NE;
122 if (cond2)
123 return SE;
124 if (cond4)
125 return NW;
126 return SW;
127 }
128 else
129 return 0;
130}
131
132/*!
133 * Add point to a given *data*.
134 */
135int quad_add_data(struct triple *point, struct quaddata *data, double dmin)
136{
137
138 int cond = 1;
139
140 if (data == NULL) {
141 fprintf(stderr, "add_data: data is NULL \n");
142 return -5;
143 }
144 for (int i = 0; i < data->n_points; i++) {
145 double xx = data->points[i].x - point->x;
146 double yy = data->points[i].y - point->y;
147 double r = xx * xx + yy * yy;
148
149 if (r <= dmin) {
150 cond = 0;
151 break;
152 }
153 }
154
155 if (cond) {
156 int n = (data->n_points)++;
157
158 data->points[n].x = point->x;
159 data->points[n].y = point->y;
160 data->points[n].z = point->z;
161 data->points[n].sm = point->sm;
162 }
163 return cond;
164}
165
166/*!
167 * Check intersection of two quaddata structures
168 *
169 * Checks if region defined by *data* intersects the region defined
170 * by *data_inter*.
171 */
172int quad_intersect(struct quaddata *data_inter, struct quaddata *data)
173{
174 double xmin, xmax, ymin, ymax;
175
176 xmin = data_inter->x_orig;
177 xmax = data_inter->xmax;
178 ymin = data_inter->y_orig;
179 ymax = data_inter->ymax;
180
181 if (((data->x_orig >= xmin) && (data->x_orig <= xmax) &&
182 (((data->y_orig >= ymin) && (data->y_orig <= ymax)) ||
183 ((ymin >= data->y_orig) && (ymin <= data->ymax)))) ||
184 ((xmin >= data->x_orig) && (xmin <= data->xmax) &&
185 (((ymin >= data->y_orig) && (ymin <= data->ymax)) ||
186 ((data->y_orig >= ymin) && (data->y_orig <= ymax))))) {
187 return 1;
188 }
189 else
190 return 0;
191}
192
193/*!
194 * Check if *data* needs to be divided
195 *
196 * Checks if *data* needs to be divided. If `data->points` is empty,
197 * returns -1; if its not empty but there aren't enough points
198 * in *data* for division returns 0. Otherwise (if its not empty and
199 * there are too many points) returns 1.
200 *
201 * \returns 1 if division is needed
202 * \returns 0 if division is not needed
203 * \returns -1 if there are no points
204 */
205int quad_division_check(struct quaddata *data, int kmax)
206{
207 if (data->points == NULL)
208 return -1;
209 if (data->n_points < kmax)
210 return 0;
211 else
212 return 1;
213}
214
215/*!
216 * Divide *data* into four new ones
217 *
218 * Divides *data* into 4 new data reinserting `data->points` in
219 * them by calling data function `quad_compare()` to determine
220 * were to insert. Returns array of 4 new data (allocates memory).
221 */
222struct quaddata **quad_divide_data(struct quaddata *data, int kmax, double dmin)
223{
224 struct quaddata **datas;
225 int cols1, cols2, rows1, rows2, i; /*j1, j2, jmin = 0; */
226 double dx, dy; /* x2, y2, dist, mindist; */
227 double xr, xm, xl, yr, ym, yl; /* left, right, middle coord */
228 double ew_res, ns_res;
229
230 ew_res = (data->xmax - data->x_orig) / data->n_cols;
231 ns_res = (data->ymax - data->y_orig) / data->n_rows;
232
233 if ((data->n_cols <= 1) || (data->n_rows <= 1)) {
235 "Points are too concentrated -- please increase DMIN\n");
236 exit(0);
237 }
238
239 if (data->n_cols % 2 == 0) {
240 cols1 = data->n_cols / 2;
241 cols2 = cols1;
242 }
243 else {
244 cols2 = (int)(data->n_cols / 2);
245 cols1 = cols2 + 1;
246 }
247 if (data->n_rows % 2 == 0) {
248 rows1 = data->n_rows / 2;
249 rows2 = rows1;
250 }
251 else {
252 rows2 = (int)(data->n_rows / 2);
253 rows1 = rows2 + 1;
254 }
255
256 dx = cols1 * ew_res;
257 dy = rows1 * ns_res;
258
259 xl = data->x_orig;
260 xm = xl + dx;
261 xr = data->xmax;
262 yl = data->y_orig;
263 ym = yl + dy;
264 yr = data->ymax;
265
266 if (!(datas = (struct quaddata **)malloc(sizeof(struct quaddata *) * 5))) {
267 return NULL;
268 }
269 datas[NE] = quad_data_new(xm, ym, xr, yr, rows2, cols2, 0, kmax);
270 datas[SW] = quad_data_new(xl, yl, xm, ym, rows1, cols1, 0, kmax);
271 datas[SE] = quad_data_new(xm, yl, xr, ym, rows1, cols2, 0, kmax);
272 datas[NW] = quad_data_new(xl, ym, xm, yr, rows2, cols1, 0, kmax);
273 for (i = 0; i < data->n_points; i++) {
274 switch (quad_compare(data->points + i, data)) {
275 case SW: {
276 quad_add_data(data->points + i, datas[SW], dmin);
277 break;
278 }
279 case SE: {
280 quad_add_data(data->points + i, datas[SE], dmin);
281 break;
282 }
283 case NW: {
284 quad_add_data(data->points + i, datas[NW], dmin);
285 break;
286 }
287 case NE: {
288 quad_add_data(data->points + i, datas[NE], dmin);
289 break;
290 }
291 }
292 }
293 data->points = NULL;
294 return datas;
295}
296
297/*!
298 * Gets such points from *data* that lie within region determined by
299 * *data_inter*. Called by tree function `region_data()`.
300 */
301int quad_get_points(struct quaddata *data_inter, struct quaddata *data, int MAX)
302{
303 int i, ind;
304 int n = 0;
305 int l = 0;
306 double xmin, xmax, ymin, ymax;
307 struct triple *point;
308
309 xmin = data_inter->x_orig;
310 xmax = data_inter->xmax;
311 ymin = data_inter->y_orig;
312 ymax = data_inter->ymax;
313 for (i = 0; i < data->n_points; i++) {
314 point = data->points + i;
315 if (l >= MAX)
316 return MAX + 1;
317 if ((point->x > xmin) && (point->x < xmax) && (point->y > ymin) &&
318 (point->y < ymax)) {
319 ind = data_inter->n_points++;
320 data_inter->points[ind].x = point->x;
321 data_inter->points[ind].y = point->y;
322 data_inter->points[ind].z = point->z;
323 data_inter->points[ind].sm = point->sm;
324 l = l + 1;
325 }
326 }
327 n = l;
328 return (n);
329}
#define NULL
Definition ccmath.h:32
int quad_add_data(struct triple *point, struct quaddata *data, double dmin)
Definition dataquad.c:135
int quad_division_check(struct quaddata *data, int kmax)
Definition dataquad.c:205
int quad_get_points(struct quaddata *data_inter, struct quaddata *data, int MAX)
Definition dataquad.c:301
int quad_intersect(struct quaddata *data_inter, struct quaddata *data)
Definition dataquad.c:172
int quad_compare(struct triple *point, struct quaddata *data)
Definition dataquad.c:91
struct triple * quad_point_new(double x, double y, double z, double sm)
Definition dataquad.c:32
struct quaddata * quad_data_new(double x_or, double y_or, double xmax, double ymax, int rows, int cols, int n_points, int kmax)
Definition dataquad.c:55
struct quaddata ** quad_divide_data(struct quaddata *data, int kmax, double dmin)
Definition dataquad.c:222
#define SE
Definition dataquad.h:27
#define SW
Definition dataquad.h:26
#define NE
Definition dataquad.h:25
#define NW
Definition dataquad.h:24
#define MAX(a, b)
Definition gis.h:145
double l
Definition r_raster.c:37
double r
Definition r_raster.c:37
void * malloc(unsigned)
void free(void *)
double ymax
Definition dataquad.h:45
double y_orig
Definition dataquad.h:43
double x_orig
Definition dataquad.h:42
struct triple * points
Definition dataquad.h:49
int n_points
Definition dataquad.h:48
double xmax
Definition dataquad.h:44
int n_cols
Definition dataquad.h:47
int n_rows
Definition dataquad.h:46
double z
Definition dataquad.h:37
double sm
Definition dataquad.h:38
double x
Definition dataquad.h:35
double y
Definition dataquad.h:36