GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
gs_util.c
Go to the documentation of this file.
1/*!
2 \file lib/ogsf/gs_util.c
3
4 \brief OGSF library - loading and manipulating surfaces
5
6 GRASS OpenGL gsurf OGSF Library
7
8 SPDX-FileCopyrightText: 1999-2008 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10
11 \author Bill Brown USACERL, GMSL/University of Illinois
12 \author Doxygenized by Martin Landa <landa.martin gmail.com> (May 2008)
13 */
14
15#include <stdlib.h>
16#include <math.h>
17#include <string.h>
18
19#include <grass/gis.h>
20#include <grass/ogsf.h>
21
22/*!
23 \brief Calculate distance between 2 coordinates
24
25 Units is one of:
26 - "meters",
27 - "miles",
28 - "kilometers",
29 - "feet",
30 - "yards",
31 - "nmiles" (nautical miles),
32 - "rods",
33 - "inches",
34 - "centimeters",
35 - "millimeters",
36 - "micron",
37 - "nanometers",
38 - "cubits",
39 - "hands",
40 - "furlongs",
41 - "chains"
42
43 Default is meters.
44
45 \param[in] from starting point (X,Y)
46 \param[in] to ending point (X,Y)
47 \param[in] units map units
48
49 \return distance between two geographic coordinates in current projection
50 */
51double GS_geodistance(double *from, double *to, const char *units)
52{
53 double meters;
54
55 meters = Gs_distance(from, to);
56
57 if (!units) {
58 return (meters);
59 }
60
61 if (strcmp(units, "meters") == 0) {
62 return (meters);
63 }
64
65 if (strcmp(units, "miles") == 0) {
66 return (meters * .0006213712);
67 }
68
69 if (strcmp(units, "kilometers") == 0) {
70 return (meters * .001);
71 }
72
73 if (strcmp(units, "feet") == 0) {
74 return (meters * 3.280840);
75 }
76
77 if (strcmp(units, "yards") == 0) {
78 return (meters * 1.093613);
79 }
80
81 if (strcmp(units, "rods") == 0) {
82 return (meters * .1988388);
83 }
84
85 if (strcmp(units, "inches") == 0) {
86 return (meters * 39.37008);
87 }
88
89 if (strcmp(units, "centimeters") == 0) {
90 return (meters * 100.0);
91 }
92
93 if (strcmp(units, "millimeters") == 0) {
94 return (meters * 1000.0);
95 }
96
97 if (strcmp(units, "micron") == 0) {
98 return (meters * 1000000.0);
99 }
100
101 if (strcmp(units, "nanometers") == 0) {
102 return (meters * 1000000000.0);
103 }
104
105 if (strcmp(units, "cubits") == 0) {
106 return (meters * 2.187227);
107 }
108
109 if (strcmp(units, "hands") == 0) {
110 return (meters * 9.842520);
111 }
112
113 if (strcmp(units, "furlongs") == 0) {
114 return (meters * .004970970);
115 }
116
117 if (strcmp(units, "nmiles") == 0) {
118 /* nautical miles */
119 return (meters * .0005399568);
120 }
121
122 if (strcmp(units, "chains") == 0) {
123 return (meters * .0497097);
124 }
125
126 return (meters);
127}
128
129/*!
130 \brief Calculate distance
131
132 \param[in] from 'from' point (X,Y,Z)
133 \param[in] to 'to' point (X,Y,Z)
134
135 \return distance
136 */
137float GS_distance(float *from, float *to)
138{
139 float x, y, z;
140
141 x = from[X] - to[X];
142 y = from[Y] - to[Y];
143 z = from[Z] - to[Z];
144
145 return (float)sqrt(x * x + y * y + z * z);
146}
147
148/*!
149 \brief Calculate distance in plane
150
151 \param[in] from 'from' point (X,Y)
152 \param[in] to 'to' point (X,Y)
153
154 \return distance
155 */
156float GS_P2distance(float *from, float *to)
157{
158 float x, y;
159
160 x = from[X] - to[X];
161 y = from[Y] - to[Y];
162
163 return (float)sqrt(x * x + y * y);
164}
165
166/*!
167 \brief Copy vector values
168
169 v1 = v2
170
171 \param[out] v1 first 3D vector (X,Y,Z)
172 \param[in] v2 second 3D vector (X,Y,Z)
173 */
174void GS_v3eq(float *v1, float *v2)
175{
176 v1[X] = v2[X];
177 v1[Y] = v2[Y];
178 v1[Z] = v2[Z];
179
180 return;
181}
182
183/*!
184 \brief Sum vectors
185
186 v1 += v2
187
188 \param[in,out] v1 first 3D vector (X,Y,Z)
189 \param[in] v2 second 3D vector (X,Y,Z)
190 */
191void GS_v3add(float *v1, float *v2)
192{
193 v1[X] += v2[X];
194 v1[Y] += v2[Y];
195 v1[Z] += v2[Z];
196
197 return;
198}
199
200/*!
201 \brief Subtract vectors
202
203 v1 -= v2
204
205 \param[in,out] v1 first 3D vector (X,Y,Z)
206 \param v2 second 3D vector (X,Y,Z)
207 */
208void GS_v3sub(float *v1, float *v2)
209{
210 v1[X] -= v2[X];
211 v1[Y] -= v2[Y];
212 v1[Z] -= v2[Z];
213
214 return;
215}
216
217/*!
218 \brief Multiple vectors
219
220 v1 *= k
221
222 \param[in,out] v1 3D vector (X,Y,Z)
223 \param[in] k multiplicator
224 */
225void GS_v3mult(float *v1, float k)
226{
227 v1[X] *= k;
228 v1[Y] *= k;
229 v1[Z] *= k;
230
231 return;
232}
233
234/*!
235 \brief Change v1 so that it is a unit vector (3D)
236
237 \param[in,out] v1 3D vector (X,Y,Z)
238
239 \return 0 if magnitude of v1 is zero
240 \return 1 if magnitude of v1 > 0
241 */
242int GS_v3norm(float *v1)
243{
244 float n;
245
246 n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
247
248 if (n == 0.0) {
249 return (0);
250 }
251
252 v1[X] /= n;
253 v1[Y] /= n;
254 v1[Z] /= n;
255
256 return (1);
257}
258
259/*!
260 \brief Change v1 so that it is a unit vector (2D)
261
262 \param[in,out] v1 2D vector (X,Y)
263
264 \return 0 if magnitude of v1 is zero
265 \return 1 if magnitude of v1 > 0
266 */
267int GS_v2norm(float *v1)
268{
269 float n;
270
271 n = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y]);
272
273 if (n == 0.0) {
274 return (0);
275 }
276
277 v1[X] /= n;
278 v1[Y] /= n;
279
280 return (1);
281}
282
283/*!
284 \brief Changes v1 so that it is a unit vector
285
286 \param[in,out] dv1 3D vector (X,Y,Z)
287
288 \return 0 if magnitude of dv1 is zero
289 \return 1 if magnitude of dv1 > 0
290 */
291int GS_dv3norm(double *dv1)
292{
293 double n;
294
295 n = sqrt(dv1[X] * dv1[X] + dv1[Y] * dv1[Y] + dv1[Z] * dv1[Z]);
296
297 if (n == 0.0) {
298 return (0);
299 }
300
301 dv1[X] /= n;
302 dv1[Y] /= n;
303 dv1[Z] /= n;
304
305 return (1);
306}
307
308/*!
309 \brief Change v2 so that v1v2 is a unit vector
310
311 \param[in] v1 first 3D vector (X,Y,Z)
312 \param[in,out] v2 second 3D vector (X,Y,Z)
313
314 \return 0 if magnitude of dx is zero
315 \return 1 if magnitude of dx > 0
316 */
317int GS_v3normalize(float *v1, float *v2)
318{
319 float n, dx, dy, dz;
320
321 dx = v2[X] - v1[X];
322 dy = v2[Y] - v1[Y];
323 dz = v2[Z] - v1[Z];
324 n = sqrt(dx * dx + dy * dy + dz * dz);
325
326 if (n == 0.0) {
327 return (0);
328 }
329
330 v2[X] = v1[X] + dx / n;
331 v2[Y] = v1[Y] + dy / n;
332 v2[Z] = v1[Z] + dz / n;
333
334 return (1);
335}
336
337/*!
338 \brief Get a normalized direction from v1 to v2, store in v3
339
340 \param[in] v1 first 3D vector (X,Y,Z)
341 \param[in] v2 second 3D vector (X,Y,Z)
342 \param[out] v3 output 3D vector (X,Y,Z)
343
344 \return 0 if magnitude of dx is zero
345 \return 1 if magnitude of dx > 0
346 */
347int GS_v3dir(float *v1, float *v2, float *v3)
348{
349 float n, dx, dy, dz;
350
351 dx = v2[X] - v1[X];
352 dy = v2[Y] - v1[Y];
353 dz = v2[Z] - v1[Z];
354 n = sqrt(dx * dx + dy * dy + dz * dz);
355
356 if (n == 0.0) {
357 v3[X] = v3[Y] = v3[Z] = 0.0;
358 return (0);
359 }
360
361 v3[X] = dx / n;
362 v3[Y] = dy / n;
363 v3[Z] = dz / n;
364
365 return (1);
366}
367
368/*!
369 \brief Get a normalized direction from v1 to v2, store in v3 (2D)
370
371 \param[in] v1 first 2D vector (X,Y)
372 \param[in] v2 second 2D vector (X,Y)
373 \param[out] v3 output 2D vector (X,Y)
374
375 \return 0 if magnitude of dx is zero
376 \return 1 if magnitude of dx > 0
377 */
378void GS_v2dir(float *v1, float *v2, float *v3)
379{
380 float n, dx, dy;
381
382 dx = v2[X] - v1[X];
383 dy = v2[Y] - v1[Y];
384 n = sqrt(dx * dx + dy * dy);
385
386 v3[X] = dx / n;
387 v3[Y] = dy / n;
388
389 return;
390}
391
392/*!
393 \brief Get the cross product v3 = v1 cross v2
394
395 \param[in] v1 first 3D vector (X,Y,Z)
396 \param[in] v2 second 3D vector (X,Y,Z)
397 \param[out] v3 output 3D vector (X,Y,Z)
398 */
399void GS_v3cross(float *v1, float *v2, float *v3)
400{
401 v3[X] = (v1[Y] * v2[Z]) - (v1[Z] * v2[Y]);
402 v3[Y] = (v1[Z] * v2[X]) - (v1[X] * v2[Z]);
403 v3[Z] = (v1[X] * v2[Y]) - (v1[Y] * v2[X]);
404
405 return;
406}
407
408/*!
409 \brief Magnitude of vector
410
411 \param[in] v1 3D vector (X,Y,Z)
412 \param[out] mag magnitude value
413 */
414void GS_v3mag(float *v1, float *mag)
415{
416 *mag = sqrt(v1[X] * v1[X] + v1[Y] * v1[Y] + v1[Z] * v1[Z]);
417
418 return;
419}
420
421/*!
422 \brief ADD
423
424 Initialize by calling with a number nhist to represent number of
425 previous entries to check, then call with zero as nhist
426
427 \param[in] p1 first point
428 \param[in] p2 second point
429 \param[in] nhist ?
430
431 \return -1 on error
432 \return -2
433 \return 1
434 \return 9
435 */
436int GS_coordpair_repeats(float *p1, float *p2, int nhist)
437{
438 static float *entrys = NULL;
439 static int next = 0;
440 static int len = 0;
441 int i;
442
443 if (nhist) {
444 if (entrys) {
445 G_free(entrys);
446 }
447
448 entrys = (float *)G_malloc(4 * nhist * sizeof(float));
449
450 if (!entrys)
451 return (-1);
452
453 len = nhist;
454 next = 0;
455 }
456
457 if (!len) {
458 return (-2);
459 }
460
461 for (i = 0; i < next; i += 4) {
462 if (entrys[i] == p1[0] && entrys[i + 1] == p1[1] &&
463 entrys[i + 2] == p2[0] && entrys[i + 3] == p2[1]) {
464 return (1);
465 }
466 }
467
468 if (len == next / 4) {
469 next = 0;
470 }
471
472 entrys[next] = p1[0];
473 entrys[next + 1] = p1[1];
474 entrys[next + 2] = p2[0];
475 entrys[next + 3] = p2[1];
476 next += 4;
477
478 return (0);
479}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_malloc(n)
Definition defs/gis.h:136
double Gs_distance(double *, double *)
Calculates distance in METERS between two points in current projection (2D)
Definition gs3.c:75
void GS_v2dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3 (2D)
Definition gs_util.c:378
void GS_v3sub(float *v1, float *v2)
Subtract vectors.
Definition gs_util.c:208
void GS_v3mult(float *v1, float k)
Multiple vectors.
Definition gs_util.c:225
void GS_v3mag(float *v1, float *mag)
Magnitude of vector.
Definition gs_util.c:414
int GS_dv3norm(double *dv1)
Changes v1 so that it is a unit vector.
Definition gs_util.c:291
int GS_coordpair_repeats(float *p1, float *p2, int nhist)
ADD.
Definition gs_util.c:436
float GS_distance(float *from, float *to)
Calculate distance.
Definition gs_util.c:137
int GS_v2norm(float *v1)
Change v1 so that it is a unit vector (2D)
Definition gs_util.c:267
void GS_v3add(float *v1, float *v2)
Sum vectors.
Definition gs_util.c:191
int GS_v3norm(float *v1)
Change v1 so that it is a unit vector (3D)
Definition gs_util.c:242
void GS_v3eq(float *v1, float *v2)
Copy vector values.
Definition gs_util.c:174
double GS_geodistance(double *from, double *to, const char *units)
Calculate distance between 2 coordinates.
Definition gs_util.c:51
float GS_P2distance(float *from, float *to)
Calculate distance in plane.
Definition gs_util.c:156
int GS_v3dir(float *v1, float *v2, float *v3)
Get a normalized direction from v1 to v2, store in v3.
Definition gs_util.c:347
int GS_v3normalize(float *v1, float *v2)
Change v2 so that v1v2 is a unit vector.
Definition gs_util.c:317
void GS_v3cross(float *v1, float *v2, float *v3)
Get the cross product v3 = v1 cross v2.
Definition gs_util.c:399
OGSF header file (structures)
#define X
Definition ogsf.h:141
#define Z
Definition ogsf.h:143
#define Y
Definition ogsf.h:142
#define x