source: grass/branches/releasebranch_5_0/src/libes/vect32_64/diglib/cont_lines.c

Last change on this file was 3, checked in by markus, 25 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id
  • Property svn:mime-type set to text/x-csrc
File size: 5.3 KB
Line 
1#include <math.h>
2#include <stdlib.h>
3#include "digit.h"
4/*
5** Written by Dave Gerdes 12/1989
6** US Army Construction Engineering Research Lab
7*/
8
9#define PI 3.14159265
10
11static double normalize_angle(double);
12
13#define LINES_INCR 10
14
15/* returns pointer to two pointers to arrays of plus_t
16** return[0] is array of the lines behind and including 'line'
17** the order starts with 'line' and goes away from it
18** return[1] is array of the lines after (not including) 'line'
19** the order is away from 'line'
20** These arrays get over-written with each call
21**
22** Each array will be terminated with a 0 value
23**
24** returns NULL on error
25*/
26plus_t **dig_get_cont_lines (
27 struct Map_info *map,
28 plus_t line,
29 double angle,
30 int twoway)
31{
32 register int cnt;
33 plus_t prev_line;
34 int i;
35 static int first_time = 1;
36 static plus_t *lines[2] ;
37 static int lines_alloc[2] ;
38
39 line = abs(line);
40
41 if (first_time)
42 {
43 if (NULL==(lines[0] = (plus_t *) malloc (LINES_INCR * sizeof (plus_t))))
44 return ((dig_out_of_memory (), (plus_t **)NULL));
45 if (NULL==(lines[1] = (plus_t *) malloc (LINES_INCR * sizeof (plus_t))))
46 return ((dig_out_of_memory (), (plus_t **)NULL));
47 lines_alloc[0] = LINES_INCR;
48 lines_alloc[1] = LINES_INCR;
49 first_time = 0;
50 }
51
52 /* follow behind then ahead */
53 for (i = 0 ; i < 2 ; i++) /* 0 behind, 1 ahead */
54 {
55 if (i == 0)
56 {
57 lines[i][0] = line;
58 prev_line = -line;
59 }
60 else
61 prev_line = line;
62
63 /* for 0 loop, start at lines[0][1] */
64 for (cnt = 1-i ; ; cnt++)
65 {
66 if (cnt >= lines_alloc[i])
67 {
68 while ((lines_alloc[i] += LINES_INCR) <= cnt)
69 ;
70 lines[i] = (plus_t *) realloc ((char *)lines[i], lines_alloc[i] * sizeof (plus_t));
71 if (lines[i] == NULL)
72 return ((dig_out_of_memory (), (plus_t **)NULL));
73 }
74 lines[i][cnt] = dig_get_next_cont_line (map, -prev_line, angle, twoway);
75 if (!lines[i][cnt]) /* no more lines */
76 {
77 break;
78 }
79 if (abs (lines[i][cnt]) == line) /* ran into ourself */
80 {
81#ifdef DEBUG
82debugf ("RAN INTO MYSELF! line %d\n", line);
83#endif
84 lines[i][cnt] = 0;
85 break;
86 }
87
88 prev_line = lines[i][cnt];
89 }
90 }
91 return (lines);
92}
93
94
95/*
96** given previous line determine next node and
97** find and return (if it exists) the number of the line that
98** is a continuation of the previous line through this node
99**
100** Note that it must leave the node at the same angle as the previous line
101** (within a tolerance "angle").
102**
103** if twoway is non-zero, then all two-way intersections will be
104** considered continuous, regardless of angle.
105*/
106
107plus_t dig_get_next_cont_line (
108 struct Map_info *map,
109 plus_t prev_line,
110 double angle,
111 int twoway)
112{
113 register int i;
114 P_NODE *Node;
115 P_LINE *Line;
116 plus_t closest_line;
117 double next_angle;
118 double closest_angle, tmp;
119 plus_t next_node;
120 int found;
121
122 closest_line = 0;
123
124 if (prev_line < 0)
125 next_node = map->Line[abs(prev_line)].N2;
126 else
127 next_node = map->Line[prev_line].N1;
128
129
130 Node = &(map->Node[next_node]);
131
132
133 if (Node->n_lines < 2)
134 return 0;
135
136 /* if twoway is set, then go ahead and check for 2 line intersection
137 ** and if found, then just return the next line
138 ** If twoway is not set, then the next line will have to pass
139 ** the rest of the tests
140 */
141 if (twoway)
142 {
143 if (Node->n_lines == 2)
144 {
145 if (Node->lines[0] == prev_line)
146 return (Node->lines[1]);
147 else
148 return (Node->lines[0]);
149 }
150 }
151
152 /* find current line in node info and get angle */
153 found = 0;
154 for (i = 0 ; i < Node->n_lines ; i++)
155 {
156 if (Node->lines[i] == prev_line)
157 {
158 double prev_angle;
159
160 prev_angle = Node->angles[i];
161 next_angle = normalize_angle (prev_angle + PI);
162#ifdef DEBUG
163debugf ("PREV ANGLE %lf, NEXT_ANGLE %lf\n", prev_angle, next_angle);
164#endif
165 found = 1;
166 break;
167 }
168 }
169 if (!found) /* ERROR: Line NOT attached to node! */
170 {
171 fprintf (stderr, "INTERNAL ERROR: Line(%d) NOT attached to node(%d)!\n", prev_line, next_node);
172 return (0);
173 }
174
175 for (i = 0 ; i < Node->n_lines ; i++)
176 {
177 if (Node->lines[i] == prev_line)
178 continue;
179
180 Line = &(map->Line[abs (Node->lines[i])]);
181
182#ifdef DEFUNCT
183 /* these are now up to the caller to check on return */
184
185 /* if different line types, continue */
186 if (type != Line->type)
187 continue;
188
189 /* if line is labelled a different value then continue */
190 /* this needs to be cleaned up to allow RE-labelling of cont lines */
191 if (cat) /* else UNLABELLING */
192 if (LINE_LABELED (Line) && cat != map->Att[Line->att].cat)
193 continue;
194#endif /*DEFUNCT*/
195
196 if (angle < (tmp = fabs (normalize_angle (Node->angles[i]-next_angle))))
197 {
198#ifdef DEBUG
199debugf (" NOT IN TOLERANCE (%lf)\n", tmp);
200#endif
201 continue;
202 }
203#ifdef DEBUG
204debugf (" *** IN TOLERANCE (%lf)\n", tmp);
205#endif
206
207 if (!closest_line)
208 {
209 closest_line = Node->lines[i];
210 closest_angle = tmp;
211 }
212 else
213 {
214 if (tmp < closest_angle)
215 {
216 closest_line = Node->lines[i];
217 closest_angle = tmp;
218 }
219 }
220 }
221
222#ifdef DEBUG
223debugf ("Returning closest line: %d\n", closest_line);
224#endif
225 return (closest_line);
226}
227
228/*
229** take angle in radians and return a normalized value
230** between -PI and PI.
231*/
232static double normalize_angle(double angle)
233{
234 while (angle < -PI)
235 angle += 2*PI;
236 while (angle > PI)
237 angle -= 2*PI;
238
239 return angle;
240}
Note: See TracBrowser for help on using the repository browser.