GRASS 8 Programmer's Manual 8.6.0dev(2026)-d2adb3a889
Loading...
Searching...
No Matches
angle.c
Go to the documentation of this file.
1/*
2 ****************************************************************************
3 *
4 * MODULE: Vector library
5 *
6 * AUTHOR(S): Original author CERL, probably Dave Gerdes.
7 * Update to GRASS 5.7 Radim Blazek.
8 *
9 * PURPOSE: Lower level functions for reading/writing/manipulating vectors.
10 *
11 * SPDX-FileCopyrightText: 2001 GRASS Development Team
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 *
14 *****************************************************************************/
15/*
16 * functions - calc_begin_angle(), and calc_end_angle()
17 * used to calculate the angle of a line to a node.
18 * returns - (float)angle (-PI ... +PI)
19 * returns - (float)(-9) if only 1 point or more points but identical
20 */
21
22#include <stdio.h>
23#include <math.h>
24#include <grass/vector.h>
25
26static double d_atan2(double, double);
27
28float dig_calc_begin_angle(const struct line_pnts *points, double thresh)
29{
30 double last_x;
31 double last_y;
32 const double *xptr;
33 const double *yptr;
34 int short_line;
35 int i;
36 int n_points;
37 const double *xarray;
38 const double *yarray;
39
40 /* temporary way to set up use of struct line_pnts */
41 n_points = points->n_points;
42 xarray = points->x;
43 yarray = points->y;
44
45 last_x = *xarray;
46 last_y = *yarray;
47 xptr = xarray + 1;
48 yptr = yarray + 1;
49
50 /* check degenerate line */
51 if (dig_line_degenerate(points) > 0)
52 return ((float)-9.);
53
54 short_line = 1;
55 if (n_points != 2) {
56 /* Search for next different coord. Note that in >= g5.7, threshold
57 * is not used for build process. */
58 /* 4.1 but do not use opposite node if there are other points */
59 for (i = 1; i < n_points - 1; i++) {
60 if ((thresh < fabs(*xptr - last_x)) ||
61 (thresh < fabs(*yptr - last_y))) {
62 short_line = 0;
63 break;
64 }
65 xptr++;
66 yptr++;
67 }
68 }
69
70 if (short_line) {
71 /* for 4.1 change this to take 1st point after node -dpg 12/92 */
72 /* return ((float) d_atan2 (yarray[n_points - 1] - last_y,
73 * xarray[n_points - 1] - last_x)); */
74 return ((float)d_atan2(yarray[1] - last_y, xarray[1] - last_x));
75 }
76
77 return ((float)d_atan2(*yptr - last_y, *xptr - last_x));
78} /* calc_begin_angle() */
79
80float dig_calc_end_angle(const struct line_pnts *points, double thresh)
81{
82 double last_x;
83 double last_y;
84 const double *xptr;
85 const double *yptr;
86 int short_line;
87 int i;
88 int n_points;
89 const double *xarray;
90 const double *yarray;
91
92 short_line = 1;
93
94 xarray = points->x;
95 yarray = points->y;
96 n_points = points->n_points;
97
98 /* check degenerate line */
99 if (dig_line_degenerate(points) > 0)
100 return ((float)-9.);
101
102 last_x = *(xarray + n_points - 1);
103 last_y = *(yarray + n_points - 1);
104 xptr = xarray + n_points - 2;
105 yptr = yarray + n_points - 2;
106
107 if (n_points != 2) {
108 /* Search for next different coord. Note that in >= g5.7, threshold
109 * is not used for build process. */
110 /* 4.1 but do not use opposite node if there are other points */
111 for (i = n_points - 2; i > 0; i--) {
112 if ((thresh < fabs(*xptr - last_x)) ||
113 (thresh < fabs(*yptr - last_y))) {
114 short_line = 0;
115 break;
116 }
117 xptr--;
118 yptr--;
119 }
120 }
121
122 if (short_line) {
123 /* updated for 4.1 to take next point away from node -dpg */
124 /* return ((float) d_atan2 (yarray[0] - last_y, xarray[0] - last_x)); */
125 return ((float)d_atan2(yarray[n_points - 2] - last_y,
126 xarray[n_points - 2] - last_x));
127 }
128
129 return ((float)d_atan2(*yptr - last_y, *xptr - last_x));
130}
131
132int dig_is_line_degenerate(const struct line_pnts *points, double thresh)
133{
134 double last_x;
135 double last_y;
136 const double *xptr;
137 const double *yptr;
138 int short_line;
139 int i;
140 int n_points;
141 const double *xarray;
142 const double *yarray;
143
144 /* temporary way to set up use of struct line_pnts */
145 n_points = points->n_points;
146 xarray = points->x;
147 yarray = points->y;
148
149 last_x = *xarray;
150 last_y = *yarray;
151 xptr = xarray + 1;
152 yptr = yarray + 1;
153
154 short_line = 1;
155 for (i = 1; i < n_points; i++) { /* Search for next different coord */
156 if ((thresh < fabs(*xptr - last_x)) ||
157 (thresh < fabs(*yptr - last_y))) {
158 short_line = 0;
159 break;
160 }
161 xptr++;
162 yptr++;
163 }
164
165 if (short_line)
166 return (1);
167
168 return (0);
169}
170
171/* Check if line is degenerate (one point or more identical points)
172 * Returns: 0 is not degenerate (but some points may be identical)
173 * 1 one point
174 * 2 more identical points
175 */
176int dig_line_degenerate(const struct line_pnts *points)
177{
178 int i, ident;
179 int n_points;
180
181 G_debug(5, "dig_line_degenerate()");
182 /* temporary way to set up use of struct line_pnts */
183 n_points = points->n_points;
184
185 if (n_points == 1) {
186 G_debug(5, " Line is degenerate (one points)");
187 return 1;
188 }
189
190 /* check identical points (= one point) */
191 ident = 1;
192 for (i = 1; i < n_points; i++) {
193 if (points->x[i] != points->x[i - 1] ||
194 points->y[i] != points->y[i - 1]) {
195 ident = 0;
196 break;
197 }
198 }
199
200 if (ident) {
201 G_debug(5, " Line is degenerate (more points)");
202 return 2;
203 }
204
205 return 0;
206}
207
208static double d_atan2(double y, double x)
209{
210 if (y == 0.0 && x == 0.0)
211 return (0.0);
212 else
213 return (atan2(y, x));
214}
float dig_calc_end_angle(const struct line_pnts *points, double thresh)
Definition angle.c:80
float dig_calc_begin_angle(const struct line_pnts *points, double thresh)
Definition angle.c:28
int dig_line_degenerate(const struct line_pnts *points)
Definition angle.c:176
int dig_is_line_degenerate(const struct line_pnts *points, double thresh)
Definition angle.c:132
int G_debug(int, const char *,...) __attribute__((format(printf
Feature geometry info - coordinates.
double * y
Array of Y coordinates.
double * x
Array of X coordinates.
int n_points
Number of points.