1 #include <stdlib.h>
2 #include <string.h>
3 #include "global.h"
4 
5 static void write_pnts(struct Map_info *, char *, char *, int, int, int);
6 
add_polyline(struct dxf_file * dxf,struct Map_info * Map)7 void add_polyline(struct dxf_file *dxf, struct Map_info *Map)
8 {
9     int code;
10     char handle[DXF_BUF_SIZE];	/* entity handle, 16 hexadecimal digits */
11     char layer[DXF_BUF_SIZE];	/* layer name */
12     int layer_flag = 0;		/* indicates if a layer name has been found */
13     int polyline_flag = 0;	/* indicates the type of polyline */
14     int warn_flag66 = 1;	/* indicates if error message printed once */
15     int vert_flag;		/* indicates that vertices are following */
16     int xflag = 0;		/* indicates if a x value has been found */
17     int yflag = 0;		/* indicates if a y value has been found */
18     int zflag = 0;		/* indicates if a z value has been found */
19     int arr_size = 0;
20 
21     /* variables to create arcs */
22     double bulge = 0.0;		/* for arc curves */
23     double prev_bulge = 0.0;	/* for arc curves */
24 
25     /* variables for polyface mesh */
26     int vertex_flag = 0;
27     int vertex_idx = 0;
28     int polyface_mesh_started = 0;
29     int mesh_pnts = 0;
30     double *mesh_xpnts = NULL;
31     double *mesh_ypnts = NULL;
32     double *mesh_zpnts = NULL;
33 
34     handle[0] = 0;
35     strcpy(layer, UNIDENTIFIED_LAYER);
36 
37     /* read in lines and process information until a 0 is read in */
38     while ((code = dxf_get_code(dxf)) != 0) {
39 	if (code == -2)
40 	    return;
41 
42 	switch (code) {
43 	case 66:		/* vertices follow flag */
44 	    vert_flag = atoi(dxf_buf);
45 	    if (vert_flag != 1)	/* flag must be always 1 */
46 		if (warn_flag66) {
47 		    G_warning(_("vertices following flag missing"));
48 		    warn_flag66 = 0;
49 		}
50 	    break;
51 	case 70:		/* polyline flag */
52 	    polyline_flag = atoi(dxf_buf);
53 
54 	    /*******************************************************************
55 	     Polyline flag (bit-coded); default is 0:
56 	     1 = This is a closed polyline (or a polygon mesh closed in
57 	         the M direction).
58 	     2 = Curve-fit vertices have been added.
59 	     4 = Spline-fit vertices have been added.
60 	     8 = This is a 3D polyline.
61 	     16 = This is a 3D polygon mesh.
62 	     32 = The polygon mesh is closed in the N direction.
63 	     64 = The polyline is a polyface mesh.
64 	     128 = The linetype pattern is generated continuously around
65 	           the vertices of this polyline.
66 	     ******************************************************************/
67 	    break;
68 	}
69     }
70 
71     zpnts[0] = 0.0;
72     /* loop until SEQEND in the dxf file */
73     while (strcmp(dxf_buf, "SEQEND") != 0) {
74 	if (feof(dxf->fp))	/* EOF */
75 	    return;
76 
77 	if (strcmp(dxf_buf, "VERTEX") == 0) {
78 	    vertex_idx++;
79 	    xflag = 0;
80 	    yflag = 0;
81 	    zflag = 0;
82 	    while ((code = dxf_get_code(dxf)) != 0) {
83 		if (code == -2)	/* EOF */
84 		    return;
85 
86 		switch (code) {
87 		case 5:	/* entity handle */
88 		    strcpy(handle, dxf_buf);
89 		    break;
90 		case 8:	/* layer name */
91 		    /* if no layer previously assigned */
92 		    if (!layer_flag && *dxf_buf) {
93 			if (flag_list) {
94 			    if (!is_layer_in_list(dxf_buf))
95 				add_layer_to_list(dxf_buf, 1);
96 			    return;
97 			}
98 			/* skip if (opt_layers != NULL && (
99 			 * (flag_invert == 0 && is_layer_in_list == 0) ||
100 			 * (flag_invert == 1 && is_layer_in_list == 1)
101 			 * )
102 			 */
103 			if (opt_layers &&
104 			    flag_invert == is_layer_in_list(dxf_buf))
105 			    return;
106 			strcpy(layer, dxf_buf);
107 			layer_flag = 1;
108 		    }
109 		    break;
110 		case 10:	/* x coordinate */
111 		    xpnts[arr_size] = atof(dxf_buf);
112 		    xflag = 1;
113 		    break;
114 		case 20:	/* y coordinate */
115 		    ypnts[arr_size] = atof(dxf_buf);
116 		    yflag = 1;
117 		    break;
118 		case 30:	/* Z coordinate */
119 		    zpnts[arr_size] = atof(dxf_buf);
120 		    zflag = 1;
121 		    break;
122 		case 40:	/* starting width */
123 		case 41:	/* ending width */
124 		    break;
125 		case 42:	/* bulge */
126 		    bulge = atof(dxf_buf);
127 		    break;
128 		case 50:	/* curve fit tangent direction */
129 		    break;
130 		case 70:	/* vertex flag */
131 		    vertex_flag = atoi(dxf_buf);
132 
133 	    /*******************************************************************
134 	     Vertex flags:
135 	     1 = Extra vertex created by curve-fitting
136 	     2 = Curve-fit tangent defined for this vertex. A curve-fit tangent
137 		 direction of 0 may be omitted from DXF output but is
138 		 significant if this bit is set.
139 	     4 = Not used
140 	     8 = Spline vertex created by spline-fitting
141 	     16 = Spline frame control point
142 	     32 = 3D polyline vertex
143 	     64 = 3D polygon mesh vertex
144 	     128 = Polyface mesh vertex
145 	     ******************************************************************/
146 		    if (vertex_flag == 16) {
147 			/* spline frame control point: don't draw it! */
148 			xflag = 0;
149 			yflag = 0;
150 			zflag = 0;
151 		    }
152 		    break;
153 		    /* NOTE: there are more cases possible */
154 		case 71:
155 		case 72:
156 		case 73:
157 		case 74:
158 		    if (!((vertex_flag & 128) && !(vertex_flag & 64)))
159 			break;
160 
161 		    if (!polyface_mesh_started) {
162 			/* save vertex coordinates to mesh_?pnts */
163 			mesh_xpnts =
164 			    (double *)G_malloc(arr_size * sizeof(double));
165 			mesh_ypnts =
166 			    (double *)G_malloc(arr_size * sizeof(double));
167 			mesh_zpnts =
168 			    (double *)G_malloc(arr_size * sizeof(double));
169 			memcpy(mesh_xpnts, xpnts, arr_size * sizeof(double));
170 			memcpy(mesh_ypnts, ypnts, arr_size * sizeof(double));
171 			memcpy(mesh_zpnts, zpnts, arr_size * sizeof(double));
172 
173 			polyface_mesh_started = 1;
174 			arr_size = 0;
175 			mesh_pnts = 0;
176 		    }
177 		    vertex_idx = atoi(dxf_buf);
178 		    if (vertex_idx > 0) {
179 			xpnts[arr_size] = mesh_xpnts[vertex_idx - 1];
180 			ypnts[arr_size] = mesh_ypnts[vertex_idx - 1];
181 			zpnts[arr_size] = mesh_zpnts[vertex_idx - 1];
182 			arr_size++;
183 			mesh_pnts++;
184 		    }
185 		    break;
186 		}
187 	    }
188 
189 	    if (polyface_mesh_started) {
190 		if (mesh_pnts > 0) {
191 		    /* close a mesh */
192 		    xpnts[arr_size] = xpnts[0];
193 		    ypnts[arr_size] = ypnts[0];
194 		    zpnts[arr_size] = zpnts[0];
195 		    arr_size++;
196 		    if (flag_frame)
197 			write_vect(Map, layer, "POLYFACE FRAME", handle, "",
198 				   arr_size, GV_LINE);
199 		    else
200 			write_vect(Map, layer, "POLYFACE", handle, "",
201 				   arr_size, GV_FACE);
202 		    arr_size = 0;
203 		    mesh_pnts = 0;
204 		}
205 		continue;
206 	    }
207 
208 	    if (xflag && yflag) {
209 		arr_size =
210 		    make_arc_from_polyline(arr_size, bulge, prev_bulge);
211 		prev_bulge = bulge;
212 		bulge = 0.0;
213 	    }			/* processing polyline vertex */
214 	}
215     }				/* vertex loop */
216 
217     if (polyface_mesh_started) {
218 	G_free(mesh_xpnts);
219 	G_free(mesh_ypnts);
220 	G_free(mesh_zpnts);
221     }
222     else
223 	write_pnts(Map, layer, handle, polyline_flag, zflag, arr_size);
224 
225     return;
226 }
227 
write_pnts(struct Map_info * Map,char * layer,char * handle,int polyline_flag,int zflag,int arr_size)228 static void write_pnts(struct Map_info *Map, char *layer, char *handle,
229 		       int polyline_flag, int zflag, int arr_size)
230 {
231     /* done reading vertices */
232     if (polyline_flag & 1) {	/* only dealing with polyline_flag = 1 */
233 	/* check to make sure vertex points describe a closed polyline */
234 	if (xpnts[0] != xpnts[arr_size - 1] ||
235 	    ypnts[0] != ypnts[arr_size - 1]) {
236 	    /* add on the vertex point to complete closed polyline */
237 	    xpnts[arr_size] = xpnts[0];
238 	    ypnts[arr_size] = ypnts[0];
239 	    zpnts[arr_size] = zpnts[0];
240 	    arr_size++;
241 
242 	    /* arr_size incremented to be consistent with polyline_flag != 1 */
243 	    if (arr_size == arr_max) {
244 		arr_max += ARR_INCR;
245 		xpnts = (double *)G_realloc(xpnts, arr_max * sizeof(double));
246 		ypnts = (double *)G_realloc(ypnts, arr_max * sizeof(double));
247 		zpnts = (double *)G_realloc(zpnts, arr_max * sizeof(double));
248 	    }
249 	}
250     }
251 
252     if (!zflag) {
253 	int i;
254 
255 	for (i = 0; i < arr_size; i++)
256 	    zpnts[i] = 0.0;
257     }
258 
259     write_vect(Map, layer, "POLYLINE", handle, "", arr_size, GV_LINE);
260 
261     return;
262 }
263