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