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