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 * COPYRIGHT: (C) 2001 by the GRASS Development Team
12 *
13 * This program is free software under the GNU General Public
14 * License (>=v2). Read the file COPYING that comes with GRASS
15 * for details.
16 *
17 *****************************************************************************/
18 /*
19 * functions - calc_begin_angle(), and calc_end_angle()
20 * used to calculate the angle of a line to a node.
21 * returns - (float)angle (-PI ... +PI)
22 * returns - (float)(-9) if only 1 point or more points but identical
23 */
24
25 #include <stdio.h>
26 #include <math.h>
27 #include <grass/vector.h>
28
29 static double d_atan2(double, double);
30
dig_calc_begin_angle(const struct line_pnts * points,double thresh)31 float dig_calc_begin_angle(const struct line_pnts *points, double thresh)
32 {
33 double last_x;
34 double last_y;
35 const double *xptr;
36 const double *yptr;
37 int short_line;
38 int i;
39 int n_points;
40 const double *xarray;
41 const double *yarray;
42
43 /* temporary way to set up use of struct line_pnts */
44 n_points = points->n_points;
45 xarray = points->x;
46 yarray = points->y;
47
48 last_x = *xarray;
49 last_y = *yarray;
50 xptr = xarray + 1;
51 yptr = yarray + 1;
52
53 /* check degenerate line */
54 if (dig_line_degenerate(points) > 0)
55 return ((float)-9.);
56
57 short_line = 1;
58 if (n_points != 2) {
59 /* Search for next different coord. Note that in >= g5.7, threshold
60 * is not used for build process. */
61 /* 4.1 but do not use opposite node if there are other points */
62 for (i = 1; i < n_points - 1; i++) {
63 if ((thresh < fabs(*xptr - last_x)) ||
64 (thresh < fabs(*yptr - last_y))) {
65 short_line = 0;
66 break;
67 }
68 xptr++;
69 yptr++;
70 }
71 }
72
73 if (short_line) {
74 /* for 4.1 change this to take 1st point after node -dpg 12/92 */
75 /* return ((float) d_atan2 (yarray[n_points - 1] - last_y, xarray[n_points - 1] - last_x)); */
76 return ((float)d_atan2(yarray[1] - last_y, xarray[1] - last_x));
77 }
78
79 return ((float)d_atan2(*yptr - last_y, *xptr - last_x));
80 } /* calc_begin_angle() */
81
dig_calc_end_angle(const struct line_pnts * points,double thresh)82 float dig_calc_end_angle(const struct line_pnts *points, double thresh)
83 {
84 double last_x;
85 double last_y;
86 const double *xptr;
87 const double *yptr;
88 int short_line;
89 int i;
90 int n_points;
91 const double *xarray;
92 const double *yarray;
93
94 short_line = 1;
95
96 xarray = points->x;
97 yarray = points->y;
98 n_points = points->n_points;
99
100 /* check degenerate line */
101 if (dig_line_degenerate(points) > 0)
102 return ((float)-9.);
103
104 last_x = *(xarray + n_points - 1);
105 last_y = *(yarray + n_points - 1);
106 xptr = xarray + n_points - 2;
107 yptr = yarray + n_points - 2;
108
109 if (n_points != 2) {
110 /* Search for next different coord. Note that in >= g5.7, threshold
111 * is not used for build process. */
112 /* 4.1 but do not use opposite node if there are other points */
113 for (i = n_points - 2; i > 0; i--) {
114 if ((thresh < fabs(*xptr - last_x)) ||
115 (thresh < fabs(*yptr - last_y))) {
116 short_line = 0;
117 break;
118 }
119 xptr--;
120 yptr--;
121 }
122 }
123
124 if (short_line) {
125 /* updated for 4.1 to take next point away from node -dpg */
126 /* return ((float) d_atan2 (yarray[0] - last_y, xarray[0] - last_x)); */
127 return ((float)
128 d_atan2(yarray[n_points - 2] - last_y,
129 xarray[n_points - 2] - last_x));
130 }
131
132 return ((float)d_atan2(*yptr - last_y, *xptr - last_x));
133 }
134
dig_is_line_degenerate(const struct line_pnts * points,double thresh)135 int dig_is_line_degenerate(const struct line_pnts *points, double thresh)
136 {
137 double last_x;
138 double last_y;
139 const double *xptr;
140 const double *yptr;
141 int short_line;
142 int i;
143 int n_points;
144 const double *xarray;
145 const double *yarray;
146
147 /* temporary way to set up use of struct line_pnts */
148 n_points = points->n_points;
149 xarray = points->x;
150 yarray = points->y;
151
152 last_x = *xarray;
153 last_y = *yarray;
154 xptr = xarray + 1;
155 yptr = yarray + 1;
156
157 short_line = 1;
158 for (i = 1; i < n_points; i++) { /* Search for next different coord */
159 if ((thresh < fabs(*xptr - last_x)) ||
160 (thresh < fabs(*yptr - last_y))) {
161 short_line = 0;
162 break;
163 }
164 xptr++;
165 yptr++;
166 }
167
168 if (short_line)
169 return (1);
170
171 return (0);
172
173 }
174
175 /* Check if line is degenerate (one point or more identical points)
176 * Returns: 0 is not degenerate (but som points may be identical)
177 * 1 one point
178 * 2 more identical points
179 */
dig_line_degenerate(const struct line_pnts * points)180 int dig_line_degenerate(const struct line_pnts *points)
181 {
182 int i, ident;
183 int n_points;
184
185 G_debug(5, "dig_line_degenerate()");
186 /* temporary way to set up use of struct line_pnts */
187 n_points = points->n_points;
188
189 if (n_points == 1) {
190 G_debug(5, " Line is degenerate (one points)");
191 return 1;
192 }
193
194 /* check identical points (= one point) */
195 ident = 1;
196 for (i = 1; i < n_points; i++) {
197 if (points->x[i] != points->x[i - 1] ||
198 points->y[i] != points->y[i - 1]) {
199 ident = 0;
200 break;
201 }
202 }
203
204 if (ident) {
205 G_debug(5, " Line is degenerate (more points)");
206 return 2;
207 }
208
209 return 0;
210 }
211
d_atan2(double y,double x)212 static double d_atan2(double y, double x)
213 {
214 if (y == 0.0 && x == 0.0)
215 return (0.0);
216 else
217 return (atan2(y, x));
218 }
219