GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
segmen2d.c
Go to the documentation of this file.
1/*!
2 * \file segmen2d.c
3 *
4 * \author H. Mitasova, I. Kosinovsky, D. Gerdes
5 *
6 * SPDX-FileCopyrightText: 1993 Helena Mitasova
7 * SPDX-FileCopyrightText: GRASS Development Team
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 *
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <grass/gis.h>
16#include <grass/glocale.h>
17#include <grass/interpf.h>
18#include <grass/gmath.h>
19
20/*!
21 * Interpolate recursively a tree of segments
22 *
23 * Recursively processes each segment in a tree by:
24 * - finding points from neighbouring segments so that the total number of
25 * points is between KMIN and KMAX2 by calling tree function MT_get_region().
26 * - creating and solving the system of linear equations using these points
27 * and interp() by calling matrix_create() and G_ludcmp().
28 * - checking the interpolating function values at points by calling
29 * check_points().
30 * - computing grid for this segment using points and interp() by calling
31 * grid_calc().
32 *
33 * \todo
34 * Isn't this in fact the updated version of the function
35 * (IL_interp_segments_new_2d)? The function IL_interp_segments_new_2d has the
36 * following, better behavior: The difference between this function and
37 * IL_interp_segments_2d() is making sure that additional points are taken from
38 * all directions, i.e. it finds equal number of points from neighboring
39 * segments in each of 8 neighborhoods.
40 */
42 struct interp_params *params,
43 struct tree_info *info, /*!< info for the quad tree */
44 struct multtree *tree, /*!< current leaf of the quad tree */
45 struct BM *bitmask, /*!< bitmask */
46 double zmin, double zmax, /*!< min and max input z-values */
47 double *zminac, double *zmaxac, /*!< min and max interp. z-values */
48 double *gmin, double *gmax, /*!< min and max inperp. slope val. */
49 double *c1min, double *c1max, /*!< min and max interp. curv. val. */
50 double *c2min, double *c2max, /*!< min and max interp. curv. val. */
51 double *ertot, /*!< total interplating func. error */
52 int totsegm, /*!< total number of segments */
53 off_t offset1, /*!< offset for temp file writing */
54 double dnorm)
55{
56 double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1, temp2;
57 int i, npt, MAXENC;
58 struct quaddata *data;
59 static int cursegm = 0;
60 static double *b = NULL;
61 static int *indx = NULL;
62 static double **matrix = NULL;
63 double ew_res, ns_res;
64 static int first_time = 1;
65 static double smseg;
66 int MINPTS;
67 double pr;
68 struct triple *point = NULL;
69 struct triple skip_point;
70 int m_skip, skip_index, j, k, segtest;
71 double xx, yy /*, zz */;
72
73 /* find the size of the smallest segment once */
74 if (first_time) {
75 smseg = smallest_segment(info->root, 4);
76 first_time = 0;
77 }
78 ns_res = (((struct quaddata *)(info->root->data))->ymax -
79 ((struct quaddata *)(info->root->data))->y_orig) /
80 params->nsizr;
81 ew_res = (((struct quaddata *)(info->root->data))->xmax -
82 ((struct quaddata *)(info->root->data))->x_orig) /
83 params->nsizc;
84
85 if (tree == NULL)
86 return -1;
87 if (tree->data == NULL)
88 return -1;
89 if (((struct quaddata *)(tree->data))->points == NULL) {
90 for (i = 0; i < 4; i++) {
91 IL_interp_segments_2d(params, info, tree->leafs[i], bitmask, zmin,
92 zmax, zminac, zmaxac, gmin, gmax, c1min,
94 dnorm);
95 }
96 return 1;
97 }
98 else {
99 distx = (((struct quaddata *)(tree->data))->n_cols * ew_res) * 0.1;
100 disty = (((struct quaddata *)(tree->data))->n_rows * ns_res) * 0.1;
101 distxp = 0;
102 distyp = 0;
103 xmn = ((struct quaddata *)(tree->data))->x_orig;
104 xmx = ((struct quaddata *)(tree->data))->xmax;
105 ymn = ((struct quaddata *)(tree->data))->y_orig;
106 ymx = ((struct quaddata *)(tree->data))->ymax;
107 i = 0;
108 MAXENC = 0;
109 /* data is a window with zero points; some fields don't make sense in
110 this case so they are zero (like resolution,dimensions */
111 /* CHANGE */
112 /* Calcutaing kmin for surrent segment (depends on the size) */
113
114 /*****if (smseg <= 0.00001) MINPTS=params->kmin; else {} ***/
115 pr = pow(2., (xmx - xmn) / smseg - 1.);
116 MINPTS = params->kmin * (pr / (1 + params->kmin * pr / params->KMAX2));
117 /* fprintf(stderr,"MINPTS=%d, KMIN=%d, KMAX=%d, pr=%lf, smseg=%lf,
118 * DX=%lf \n", MINPTS,params->kmin,params->KMAX2,pr,smseg,xmx-xmn); */
119
120 data = (struct quaddata *)quad_data_new(xmn - distx, ymn - disty,
121 xmx + distx, ymx + disty, 0, 0,
122 0, params->KMAX2);
123 npt = MT_region_data(info, info->root, data, params->KMAX2, 4);
124
125 while ((npt < MINPTS) || (npt > params->KMAX2)) {
126 if (i >= 70) {
127 G_warning(
128 _("Taking too long to find points for interpolation - "
129 "please change the region to area where your points are. "
130 "Continuing calculations..."));
131 break;
132 }
133 i++;
134 if (npt > params->KMAX2)
135 /* decrease window */
136 {
137 MAXENC = 1;
138 temp1 = distxp;
139 distxp = distx;
140 distx = distxp - fabs(distx - temp1) * 0.5;
141 temp2 = distyp;
142 distyp = disty;
143 disty = distyp - fabs(disty - temp2) * 0.5;
144 /* decrease by 50% of a previous change in window */
145 }
146 else {
147 temp1 = distyp;
148 distyp = disty;
149 temp2 = distxp;
150 distxp = distx;
151 if (MAXENC) {
152 disty = fabs(disty - temp1) * 0.5 + distyp;
153 distx = fabs(distx - temp2) * 0.5 + distxp;
154 }
155 else {
156 distx += distx;
157 disty += disty;
158 }
159 /* decrease by 50% of extra distance */
160 }
161 data->x_orig = xmn - distx; /* update window */
162 data->y_orig = ymn - disty;
163 data->xmax = xmx + distx;
164 data->ymax = ymx + disty;
165 data->n_points = 0;
166 npt = MT_region_data(info, info->root, data, params->KMAX2, 4);
167 }
168
169 if (totsegm != 0) {
171 }
172 data->n_rows = ((struct quaddata *)(tree->data))->n_rows;
173 data->n_cols = ((struct quaddata *)(tree->data))->n_cols;
174
175 /* for printing out overlapping segments */
176 ((struct quaddata *)(tree->data))->x_orig = xmn - distx;
177 ((struct quaddata *)(tree->data))->y_orig = ymn - disty;
178 ((struct quaddata *)(tree->data))->xmax = xmx + distx;
179 ((struct quaddata *)(tree->data))->ymax = ymx + disty;
180
181 data->x_orig = xmn;
182 data->y_orig = ymn;
183 data->xmax = xmx;
184 data->ymax = ymx;
185
186 if (!matrix) {
187 if (!(matrix =
188 G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
189 G_warning(_("Out of memory"));
190 return -1;
191 }
192 }
193 if (!indx) {
194 if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
195 G_warning(_("Out of memory"));
196 return -1;
197 }
198 }
199 if (!b) {
200 if (!(b = G_alloc_vector(params->KMAX2 + 3))) {
201 G_warning(_("Out of memory"));
202 return -1;
203 }
204 }
205 /* allocate memory for CV points only if cv is performed */
206 if (params->cv) {
207 if (!(point = (struct triple *)G_malloc(sizeof(struct triple) *
208 data->n_points))) {
209 G_warning(_("Out of memory"));
210 return -1;
211 }
212 }
213
214 /*normalize the data so that the side of average segment is about 1m */
215 /* put data_points into point only if CV is performed */
216
217 for (i = 0; i < data->n_points; i++) {
218 data->points[i].x = (data->points[i].x - data->x_orig) / dnorm;
219 data->points[i].y = (data->points[i].y - data->y_orig) / dnorm;
220 if (params->cv) {
221 point[i].x = data->points[i].x; /*cv stuff */
222 point[i].y = data->points[i].y; /*cv stuff */
223 point[i].z = data->points[i].z; /*cv stuff */
224 }
225
226 /* commented out by Helena january 1997 as this is not necessary
227 although it may be useful to put normalization of z back?
228 data->points[i].z = data->points[i].z / dnorm;
229 this made smoothing self-adjusting based on dnorm
230 if (params->rsm < 0.) data->points[i].sm = data->points[i].sm /
231 dnorm;
232 */
233 }
234
235 /* cv stuff */
236 if (params->cv)
237 m_skip = data->n_points;
238 else
239 m_skip = 1;
240
241 /* remove after cleanup - this is just for testing */
242 skip_point.x = 0.;
243 skip_point.y = 0.;
244 skip_point.z = 0.;
245
246 /*** TODO: parallelize this loop instead of the LU solver! ***/
247 for (skip_index = 0; skip_index < m_skip; skip_index++) {
248 if (params->cv) {
249 segtest = 0;
250 j = 0;
251 xx =
252 point[skip_index].x * dnorm + data->x_orig + params->x_orig;
253 yy =
254 point[skip_index].y * dnorm + data->y_orig + params->y_orig;
255 /* zz = point[skip_index].z; */
256 if (xx >= data->x_orig + params->x_orig &&
257 xx <= data->xmax + params->x_orig &&
258 yy >= data->y_orig + params->y_orig &&
259 yy <= data->ymax + params->y_orig) {
260 segtest = 1;
261 skip_point.x = point[skip_index].x;
262 skip_point.y = point[skip_index].y;
263 skip_point.z = point[skip_index].z;
264 for (k = 0; k < m_skip; k++) {
265 if (k != skip_index && params->cv) {
266 data->points[j].x = point[k].x;
267 data->points[j].y = point[k].y;
268 data->points[j].z = point[k].z;
269 j++;
270 }
271 }
272 } /* segment area test */
273 }
274 if (!params->cv) {
275 if (params->matrix_create(params, data->points, data->n_points,
276 matrix, indx) < 0)
277 return -1;
278 }
279 else if (segtest == 1) {
280 if (params->matrix_create(params, data->points,
281 data->n_points - 1, matrix,
282 indx) < 0) {
283 G_free(point);
284 return -1;
285 }
286 }
287 if (!params->cv) {
288 for (i = 0; i < data->n_points; i++)
289 b[i + 1] = data->points[i].z;
290 b[0] = 0.;
291 G_lubksb(matrix, data->n_points + 1, indx, b);
292 /* put here condition to skip error if not needed */
293 params->check_points(params, data, b, ertot, zmin, dnorm,
294 &skip_point);
295 }
296 else if (segtest == 1) {
297 for (i = 0; i < data->n_points - 1; i++)
298 b[i + 1] = data->points[i].z;
299 b[0] = 0.;
300 G_lubksb(matrix, data->n_points, indx, b);
301 params->check_points(params, data, b, ertot, zmin, dnorm,
302 &skip_point);
303 }
304 } /*end of cv loop */
305
306 if (!params->cv)
307 if ((params->Tmp_fd_z != NULL) || (params->Tmp_fd_dx != NULL) ||
308 (params->Tmp_fd_dy != NULL) || (params->Tmp_fd_xx != NULL) ||
309 (params->Tmp_fd_yy != NULL) || (params->Tmp_fd_xy != NULL)) {
310
311 if (params->grid_calc(params, data, bitmask, zmin, zmax, zminac,
313 c2max, ertot, b, offset1, dnorm) < 0)
314 return -1;
315 }
316
317 /* show after to catch 100% */
318 cursegm++;
319 if (totsegm < cursegm)
320 G_debug(1, "%d %d", totsegm, cursegm);
321
322 if (totsegm != 0) {
324 }
325 /*
326 G_free_matrix(matrix);
327 G_free_ivector(indx);
328 G_free_vector(b);
329 */
330 G_free(data->points);
331 G_free(data);
332 }
333 G_free(point);
334 return 1;
335}
336
337double smallest_segment(struct multtree *tree, int n_leafs)
338{
339 static int first_time = 1;
340 int ii;
341 static double minside;
342 double side;
343
344 if (tree == NULL)
345 return 0;
346 if (tree->data == NULL)
347 return 0;
348 if (tree->leafs != NULL) {
349 for (ii = 0; ii < n_leafs; ii++) {
350 side = smallest_segment(tree->leafs[ii], n_leafs);
351 if (first_time) {
352 minside = side;
353 first_time = 0;
354 }
355 if (side < minside)
356 minside = side;
357 }
358 }
359 else {
360 side = ((struct quaddata *)(tree->data))->xmax -
361 ((struct quaddata *)(tree->data))->x_orig;
362 return side;
363 }
364
365 return minside;
366}
#define NULL
Definition ccmath.h: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
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:59
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
int * G_alloc_ivector(size_t)
Vector matrix memory allocation.
Definition ialloc.c:38
void G_lubksb(double **a, int n, int *indx, double b[])
LU backward substitution.
Definition lu.c:98
double * G_alloc_vector(size_t)
Vector matrix memory allocation.
Definition dalloc.c:38
double ** G_alloc_matrix(int, int)
Matrix memory allocation.
Definition dalloc.c:55
#define _(str)
Definition glocale.h:10
int MT_region_data(struct tree_info *info, struct multtree *tree, struct quaddata *data, int MAX, int n_leafs)
Definition qtree.c:182
double b
Definition r_raster.c:37
double smallest_segment(struct multtree *tree, int n_leafs)
Definition segmen2d.c:337
int IL_interp_segments_2d(struct interp_params *params, struct tree_info *info, struct multtree *tree, struct BM *bitmask, double zmin, double zmax, double *zminac, double *zmaxac, double *gmin, double *gmax, double *c1min, double *c1max, double *c2min, double *c2max, double *ertot, int totsegm, off_t offset1, double dnorm)
Definition segmen2d.c:41
Definition bitmap.h:17
check_points_fn * check_points
Definition interpf.h:132
FILE * Tmp_fd_xx
Definition interpf.h:123
FILE * Tmp_fd_xy
Definition interpf.h:123
FILE * Tmp_fd_yy
Definition interpf.h:123
grid_calc_fn * grid_calc
Definition interpf.h:128
double x_orig
Definition interpf.h:112
FILE * Tmp_fd_dx
Definition interpf.h:123
double y_orig
Definition interpf.h:112
FILE * Tmp_fd_z
Definition interpf.h:123
FILE * Tmp_fd_dy
Definition interpf.h:123
matrix_create_fn * matrix_create
Definition interpf.h:130
struct multtree ** leafs
Definition qtree.h:50
struct quaddata * data
Definition qtree.h:49
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
struct multtree * root
Definition qtree.h:45
double z
Definition dataquad.h:37
double x
Definition dataquad.h:35
double y
Definition dataquad.h:36