1 /* Cell-file line extraction */
2 /* Input/output and line tracing routines */
3
4 /* Mike Baba */
5 /* DBA Systems */
6 /* Farfax, VA */
7 /* Jan 1990 */
8
9 /* Jean Ezell */
10 /* US Army Corps of Engineers */
11 /* Construction Engineering Research Lab */
12 /* Modelling and Simulation Team */
13 /* Champaign, IL 61820 */
14 /* March 1988 */
15
16 /* input is a GRASS raster map */
17 /* output is a binary or ascii digit file */
18
19 /*
20 * Modified for the new Grass 5.0 floating point and
21 * null values raster map format.
22 * Pierre de Mouveaux - 20 april 2000.
23 */
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #ifdef __MINGW32__
30 #include <process.h>
31 #else
32 #include <sys/wait.h>
33 #endif
34
35 #include <grass/gis.h>
36 #include <grass/glocale.h>
37 #include <grass/dbmi.h>
38 #include <grass/vector.h>
39 #include "global.h"
40
41
42 /* function prototypes */
43 static int write_ln(struct COOR *, struct COOR *, int);
44
45
46 /* write_line - attempt to write a line to output */
47 /* just returns if line is not completed yet */
48
write_line(struct COOR * seed)49 int write_line(struct COOR *seed)
50 {
51 struct COOR *point, *begin, *end, *last;
52 int dir, line_type, n, n1;
53
54 point = seed;
55 if ((dir = at_end(point))) { /* already have one end of line */
56 begin = point;
57 end = find_end(point, dir, &line_type, &n);
58 if (line_type == OPEN) {
59 return (-1); /* unfinished line */
60 }
61 direction = dir;
62 }
63 else { /* in middle of a line */
64 end = find_end(point, FORWARD, &line_type, &n);
65 if (line_type == OPEN) { /* line not finished */
66 return (-1);
67 }
68
69 if (line_type == END) { /* found one end at least *//* look for other one */
70 begin = find_end(point, BACKWARD, &line_type, &n1);
71 if (line_type == OPEN) { /* line not finished */
72 return (-1);
73 }
74
75 if (line_type == LOOP) { /* this should NEVER be the case */
76 G_warning(_("write_line: found half a loop!"));
77 return (-1);
78 }
79
80 direction = at_end(begin); /* found both ends now; total length */
81 n += n1; /* is sum of distances to each end */
82 }
83 else { /* line_type = LOOP by default */
84 /* already have correct length */
85 begin = end; /* end and beginning are the same */
86 direction = FORWARD; /* direction is arbitrary */
87 }
88 }
89
90 dir = direction;
91
92 /* if (n > 2) */
93 write_ln(begin, end, n);
94
95 /* now free all the pointers */
96 direction = dir;
97 point = begin;
98
99 /* skip first and last point */
100 while ((point = move(point)) == begin);
101
102 while (point && point != end) {
103 last = point;
104
105 point = move(point);
106 if (point == last) {
107 /* should not happen */
108 G_warning("loop during free ptrs, ptr %d of %d", n1, n);
109 point = move(point);
110 }
111
112 if (last->fptr != NULL)
113 if (last->fptr->fptr == last)
114 last->fptr->fptr = NULL;
115
116 /* now it can already ne NULL */
117 if (last->fptr != NULL)
118 if (last->fptr->bptr == last)
119 last->fptr->bptr = NULL;
120 if (last->bptr != NULL)
121 if (last->bptr->fptr == last)
122 last->bptr->fptr = NULL;
123 if (last->bptr != NULL)
124 if (last->bptr->bptr == last)
125 last->bptr->bptr = NULL;
126 free_ptr(last);
127 } /* end of for i */
128
129 if (point != end) {
130 /* should not happen */
131 G_warning("Line end not reached, possible memory leak");
132 }
133
134 /* free first and last point */
135 free_ptr(begin);
136 if (end != begin)
137 free_ptr(end);
138
139 return (0);
140 }
141
142 /* write_ln - actual writing part of write_line */
143 /* writes binary and supplemental file */
144
write_ln(struct COOR * begin,struct COOR * end,int n)145 static int write_ln(struct COOR *begin, struct COOR *end, /* start and end point of line */
146 int n)
147 { /* number of points to write */
148 static struct line_pnts *points = NULL;
149 double x, y;
150 struct COOR *p, *last;
151 int i, cat, field;
152 static int count = 1;
153
154 if (!points)
155 points = Vect_new_line_struct();
156 Vect_reset_line(points);
157
158 field = 1;
159
160 Vect_reset_cats(Cats);
161
162 p = begin;
163 y = cell_head.north - ((double)p->row + 0.5) * cell_head.ns_res;
164 x = cell_head.west + ((double)p->col + 0.5) * cell_head.ew_res;
165
166 /* value_flag is used only for CELL type */
167 cat = (value_flag) ? p->val : count;
168
169 Vect_cat_set(Cats, field, cat);
170 Vect_append_point(points, x, y, 0.0);
171
172 for (i = 0; i < n; i++) {
173 last = p;
174
175 /* this should NEVER happen */
176 if ((p = move(p)) == NULL)
177 G_fatal_error(_("write_line: line terminated unexpectedly\n"
178 " previous (%d) point %d (%d,%d,%d) %p %p"),
179 direction, i, last->row, last->col, last->node,
180 (void *)last->fptr, (void *)last->bptr);
181
182 y = cell_head.north - ((double)p->row + 0.5) * cell_head.ns_res;
183 x = cell_head.west + ((double)p->col + 0.5) * cell_head.ew_res;
184
185 if (p->val != cat && value_flag) {
186 Vect_append_point(points, x, y, 0.0);
187
188 if ((driver != NULL) && !value_flag) {
189 insert_value(cat, p->val, p->dval);
190 }
191
192 Vect_write_line(&Map, GV_LINE, points, Cats);
193 Vect_reset_line(points);
194 Vect_reset_cats(Cats);
195 cat = (value_flag) ? p->val : (++count);
196 Vect_cat_set(Cats, field, cat);
197 }
198
199 Vect_append_point(points, x, y, 0.0);
200 }
201
202 if ((driver != NULL) && !value_flag) {
203 insert_value(cat, p->val, p->dval);
204 }
205
206 Vect_write_line(&Map, GV_LINE, points, Cats);
207
208 count++;
209
210 return 0;
211 }
212