1 /* **************************************************************
2 *
3 * MODULE: v.in.dwg
4 *
5 * AUTHOR(S): Radim Blazek
6 *
7 * PURPOSE: Import of DWG/DXF files
8 *
9 * COPYRIGHT: (C) 2001 by the GRASS Development Team
10 *
11 * This program is free software under the
12 * GNU General Public License (>=v2).
13 * Read the file COPYING that comes with GRASS
14 * for details.
15 *
16 * In addition, as a special exception, Radim Blazek gives permission
17 * to link the code of this program with the OpenDWG libraries (or with
18 * modified versions of the OpenDWG libraries that use the same license
19 * as OpenDWG libraries), and distribute linked combinations including the two.
20 * You must obey the GNU General Public License in all respects for all
21 * of the code used other than. If you modify this file, you may extend
22 * this exception to your version of the file, but you are not obligated
23 * to do so. If you do not wish to do so, delete this exception statement
24 * from your version.
25 *
26 * **************************************************************/
27
28 /* Documentation:
29 * http://www.opendwg.org
30 * -> OpenDWG Toolkit Reference
31 *
32 * Unsupported entities must be added in wrentity()
33 *
34 * TODO: 3rd dimension is not functional for CIRCLE and ARC
35 * -> required updated of transformation in INSERT
36 * (how to do that??)
37 */
38
39 #define AD_PROTOTYPES
40 #define AD_VM_PC
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <math.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <grass/gis.h>
49 #include <grass/dbmi.h>
50 #include <grass/vector.h>
51 #include "ad2.h"
52 #include "global.h"
53
54 #define exampleprintf printf
55 #define LOCPI M_PI
56
57 char buf[1000];
58 char buf2[1000];
59
getEntTypeName(PAD_ENT_HDR adenhd,char * name)60 void getEntTypeName(PAD_ENT_HDR adenhd, char *name)
61 {
62 switch (adenhd->enttype) {
63 case AD_ENT_LINE:
64 strcpy(name, "LINE");
65 break;
66 case AD_ENT_POINT:
67 strcpy(name, "POINT");
68 break;
69 case AD_ENT_CIRCLE:
70 strcpy(name, "CIRCLE");
71 break;
72 case AD_ENT_SHAPE:
73 strcpy(name, "SHAPE");
74 break;
75 case AD_ENT_ELLIPSE:
76 strcpy(name, "ELLIPSE");
77 break;
78 case AD_ENT_SPLINE:
79 strcpy(name, "SPLINE");
80 break;
81 case AD_ENT_TEXT:
82 strcpy(name, "TEXT");
83 break;
84 case AD_ENT_ARC:
85 strcpy(name, "ARC");
86 break;
87 case AD_ENT_TRACE:
88 strcpy(name, "TRACE");
89 break;
90 case AD_ENT_SOLID:
91 strcpy(name, "SOLID");
92 break;
93 case AD_ENT_BLOCK:
94 strcpy(name, "BLOCK");
95 break;
96 case AD_ENT_ENDBLK:
97 strcpy(name, "ENDBLK");
98 break;
99 case AD_ENT_INSERT:
100 strcpy(name, "INSERT");
101 break;
102 case AD_ENT_ATTDEF:
103 strcpy(name, "ATTDEF");
104 break;
105 case AD_ENT_ATTRIB:
106 strcpy(name, "ATTRIB");
107 break;
108 case AD_ENT_SEQEND:
109 strcpy(name, "SEQEND");
110 break;
111 case AD_ENT_POLYLINE:
112 strcpy(name, "POLYLINE");
113 break;
114 case AD_ENT_VERTEX:
115 strcpy(name, "VERTEX");
116 break;
117 case AD_ENT_LINE3D:
118 strcpy(name, "3DLINE");
119 break;
120 case AD_ENT_FACE3D:
121 strcpy(name, "3DFACE");
122 break;
123 case AD_ENT_DIMENSION:
124 strcpy(name, "DIMENSION");
125 break;
126 case AD_ENT_VIEWPORT:
127 strcpy(name, "VIEWPORT");
128 break;
129 case AD_ENT_SOLID3D:
130 strcpy(name, "SOLID3D");
131 break;
132 case AD_ENT_RAY:
133 strcpy(name, "RAY");
134 break;
135 case AD_ENT_XLINE:
136 strcpy(name, "XLINE");
137 break;
138 case AD_ENT_MTEXT:
139 strcpy(name, "MTEXT");
140 break;
141 case AD_ENT_LEADER:
142 strcpy(name, "LEADER");
143 break;
144 case AD_ENT_TOLERANCE:
145 strcpy(name, "TOLERANCE");
146 break;
147 case AD_ENT_MLINE:
148 strcpy(name, "MLINE");
149 break;
150 case AD_ENT_BODY:
151 strcpy(name, "BODY");
152 break;
153 case AD_ENT_REGION:
154 strcpy(name, "REGION");
155 break;
156 default:
157 if (adenhd->enttype == adOle2frameEnttype(dwghandle))
158 strcpy(name, "OLE2FRAME");
159 else if (adenhd->enttype == adLwplineEnttype(dwghandle))
160 strcpy(name, "LWPOLYLINE");
161 else if (adenhd->enttype == adHatchEnttype(dwghandle))
162 strcpy(name, "HATCH");
163 else if (adenhd->enttype == adImageEnttype(dwghandle))
164 strcpy(name, "IMAGE");
165 else if (adenhd->enttype == adArcAlignedTextEnttype(dwghandle))
166 strcpy(name, "ArcAlignedText");
167 else if (adenhd->enttype == adWipeoutEnttype(dwghandle))
168 strcpy(name, "Wipeout");
169 else if (adenhd->enttype == adRtextEnttype(dwghandle))
170 strcpy(name, "Rtext");
171 else { /* regular proxy */
172
173 G_debug(3, "adenhd->enttype: %d", adenhd->enttype);
174 strcpy(name, "Proxy");
175 }
176 break;
177 }
178 }
179
write_line(PAD_ENT_HDR adenhd,int type,int level)180 int write_line(PAD_ENT_HDR adenhd, int type, int level)
181 {
182 int i, l;
183 double x, y, z, r, ang;
184
185 adSeekLayer(dwghandle, adenhd->entlayerobjhandle, Layer);
186
187 /* Transformation, go up through all levels of transformation */
188 /* not sure what is the right order of transformation */
189 for (l = level; l >= 0; l--) {
190 for (i = 0; i < Points->n_points; i++) {
191 /* scale */
192 x = Points->x[i] * Trans[l].xscale;
193 y = Points->y[i] * Trans[l].yscale;
194 z = Points->z[i] * Trans[l].zscale;
195 /* rotate */
196 r = sqrt(x * x + y * y);
197 ang = atan2(y, x) + Trans[l].rotang;
198 x = r * cos(ang);
199 y = r * sin(ang);
200 /* move */
201 x += Trans[l].dx;
202 y += Trans[l].dy;
203 z += Trans[l].dz;
204 Points->x[i] = x;
205 Points->y[i] = y;
206 Points->z[i] = z;
207 }
208 }
209
210 Vect_reset_cats(Cats);
211 Vect_cat_set(Cats, 1, cat);
212 Vect_write_line(&Map, type, Points, Cats);
213
214 /* Cat */
215 sprintf(buf, "insert into %s values ( %d", Fi->table, cat);
216 db_set_string(&sql, buf);
217
218 /* Entity name */
219 getEntTypeName(adenhd, buf2);
220 sprintf(buf, ", '%s'", buf2);
221 db_append_string(&sql, buf);
222
223 /* Color */
224 sprintf(buf, ", %d", adenhd->entcolor);
225 db_append_string(&sql, buf);
226
227 /* Weight */
228 sprintf(buf, ", %d", adenhd->lineweight);
229 db_append_string(&sql, buf);
230
231 /* Layer name */
232 if (!Layer->purgedflag && Layer->name != NULL) {
233 db_set_string(&str, Layer->name);
234 db_double_quote_string(&str);
235 sprintf(buf, ", '%s'", db_get_string(&str));
236 }
237 else {
238 sprintf(buf, ", ''");
239 }
240 db_append_string(&sql, buf);
241
242 /* Block name */
243 if (Block != NULL) {
244 db_set_string(&str, Block);
245 db_double_quote_string(&str);
246 }
247 else {
248 db_set_string(&str, "");
249 }
250 sprintf(buf, ", '%s'", db_get_string(&str));
251 db_append_string(&sql, buf);
252
253 /* Text */
254 if (Txt != NULL) {
255 db_set_string(&str, Txt);
256 db_double_quote_string(&str);
257 }
258 else {
259 db_set_string(&str, "");
260 }
261 sprintf(buf, ", '%s'", db_get_string(&str));
262 db_append_string(&sql, buf);
263
264 db_append_string(&sql, ")");
265 G_debug(3, db_get_string(&sql));
266
267 if (db_execute_immediate(driver, &sql) != DB_OK) {
268 db_close_database(driver);
269 db_shutdown_driver(driver);
270 G_fatal_error("Cannot insert new row: %s", db_get_string(&sql));
271 }
272
273 cat++;
274 return 0;
275 }
276
277 /* Returns 1 if element has geometry and may be written to vector */
is_low_level(PAD_ENT_HDR adenhd)278 int is_low_level(PAD_ENT_HDR adenhd)
279 {
280 if (adenhd->enttype == AD_ENT_BLOCK || adenhd->enttype == AD_ENT_ENDBLK ||
281 adenhd->enttype == AD_ENT_SEQEND || adenhd->enttype == AD_ENT_INSERT)
282 {
283 return 0;
284 }
285 return 1;
286 }
287
wrentity(PAD_ENT_HDR adenhd,PAD_ENT aden,int level,AD_VMADDR entlist,int circle_as_point)288 void wrentity(PAD_ENT_HDR adenhd, PAD_ENT aden, int level, AD_VMADDR entlist,
289 int circle_as_point)
290 {
291 short ret;
292 PAD_BLOB_CTRL bcptr;
293 PAD_ENT_HDR adenhd2;
294 PAD_ENT aden2;
295 OdaLong il;
296 double tempdouble[3], tempbulge, tempwidth[3];
297 double x, y, z, ang;
298 PAD_BLKH adblkh;
299 int layer_found = 1;
300
301 if (is_low_level(adenhd))
302 n_elements++;
303
304 /* Check layer name */
305 if (layers_opt->answers) {
306 int i = 0;
307
308 adSeekLayer(dwghandle, adenhd->entlayerobjhandle, Layer);
309
310 layer_found = 0;
311 if (!Layer->purgedflag) {
312 while (layers_opt->answers[i]) {
313 if (strcmp(Layer->name, layers_opt->answers[i]) == 0) {
314 layer_found = 1;
315 break;
316 }
317 i++;
318 }
319 }
320
321 if ((!invert_flag->answer && !layer_found) ||
322 (invert_flag->answer && layer_found)) {
323 if (is_low_level(adenhd))
324 n_skipped++;
325 if (adenhd->enttype != AD_ENT_INSERT &&
326 adenhd->enttype != AD_ENT_POLYLINE)
327 return;
328 }
329 }
330
331 getEntTypeName(adenhd, buf);
332 G_debug(1, "Entity: %s", buf);
333
334 Txt = NULL;
335 adenhd2 = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR));
336 aden2 = (PAD_ENT) G_malloc(sizeof(AD_ENT));
337 adblkh = (PAD_BLKH) G_malloc(sizeof(AD_BLKH));
338 Vect_reset_line(Points);
339
340 /* Check space for lower level */
341 if (level + 1 == atrans) {
342 atrans += 10;
343 Trans = (TRANS *) G_realloc(Trans, atrans * sizeof(TRANS));
344 }
345
346 switch (adenhd->enttype) {
347 case AD_ENT_LINE:
348 Vect_append_point(Points, aden->line.pt0[0], aden->line.pt0[1],
349 aden->line.pt0[2]);
350 Vect_append_point(Points, aden->line.pt1[0], aden->line.pt1[1],
351 aden->line.pt1[2]);
352 write_line(adenhd, GV_LINE, level);
353 break;
354
355 case AD_ENT_FACE3D:
356 Vect_append_point(Points, aden->face3d.pt0[0], aden->face3d.pt0[1],
357 aden->face3d.pt0[2]);
358 Vect_append_point(Points, aden->face3d.pt1[0], aden->face3d.pt1[1],
359 aden->face3d.pt1[2]);
360 Vect_append_point(Points, aden->face3d.pt2[0], aden->face3d.pt2[1],
361 aden->face3d.pt2[2]);
362 Vect_append_point(Points, aden->face3d.pt3[0], aden->face3d.pt3[1],
363 aden->face3d.pt3[2]);
364 write_line(adenhd, GV_FACE, level);
365 break;
366
367 case AD_ENT_SOLID:
368 Vect_append_point(Points, aden->solid.pt0[0], aden->solid.pt0[1],
369 aden->solid.pt0[2]);
370 Vect_append_point(Points, aden->solid.pt1[0], aden->solid.pt1[1],
371 aden->solid.pt1[2]);
372 Vect_append_point(Points, aden->solid.pt2[0], aden->solid.pt2[1],
373 aden->solid.pt2[2]);
374 Vect_append_point(Points, aden->solid.pt3[0], aden->solid.pt3[1],
375 aden->solid.pt3[2]);
376 write_line(adenhd, GV_FACE, level);
377 break;
378
379 case AD_ENT_TEXT:
380 Txt = aden->text.textstr;
381 Vect_append_point(Points, aden->text.pt0[0], aden->text.pt0[1],
382 aden->line.pt0[2]);
383 write_line(adenhd, GV_POINT, level);
384 break;
385
386
387 case AD_ENT_POINT:
388 Vect_append_point(Points, aden->point.pt0[0], aden->point.pt0[1],
389 aden->line.pt0[2]);
390 write_line(adenhd, GV_POINT, level);
391 break;
392
393 case AD_ENT_ARC:
394 for (ang = aden->arc.stang; ang < aden->arc.endang;
395 ang += 2 * LOCPI / 360) {
396 x = aden->arc.pt0[0] + aden->arc.radius * cos(ang);
397 y = aden->arc.pt0[1] + aden->arc.radius * sin(ang);
398 z = aden->arc.pt0[2];
399 Vect_append_point(Points, x, y, z);
400 }
401 x = aden->arc.pt0[0] + aden->arc.radius * cos(aden->arc.endang);
402 y = aden->arc.pt0[1] + aden->arc.radius * sin(aden->arc.endang);
403 z = aden->arc.pt0[2];
404 Vect_append_point(Points, x, y, z);
405 write_line(adenhd, GV_LINE, level);
406 break;
407
408 case AD_ENT_CIRCLE:
409 if (circle_as_point) {
410 Vect_append_point(Points, aden->circle.pt0[0],
411 aden->circle.pt0[1], aden->circle.pt0[3]);
412 write_line(adenhd, GV_POINT, level);
413 }
414 else {
415 for (ang = 0; ang < 2 * LOCPI; ang += 2 * LOCPI / 360) {
416 x = aden->circle.pt0[0] + aden->circle.radius * cos(ang);
417 y = aden->circle.pt0[1] + aden->circle.radius * sin(ang);
418 z = aden->circle.pt0[3];
419 Vect_append_point(Points, x, y, z);
420 }
421 Vect_append_point(Points, Points->x[0], Points->y[0],
422 Points->z[0]);
423 write_line(adenhd, GV_LINE, level);
424 }
425 break;
426
427 /* BLOCK starts block of entities but makes no transformation - is it right ?
428 * -> do nothing just warn for xref */
429 case AD_ENT_BLOCK:
430 if (aden->block.xrefpath[0]) {
431 G_warning
432 ("External reference for block not supported.\n xref: %s",
433 aden->block.xrefpath);
434 }
435 Block = G_store(aden->block.name2);
436 break;
437
438 case AD_ENT_ENDBLK: /* endblk - no data */
439 G_free(Block);
440 Block = NULL;
441 break;
442
443 case AD_ENT_INSERT: /* insert */
444 /* get transformation */
445 /* TODO: fix rotation for CIRCLE and ARC */
446 G_debug(3, " x,y,z: %f, %f, %f", aden->insert.pt0[0],
447 aden->insert.pt0[1], aden->insert.pt0[2]);
448 G_debug(3, " xscale, yscale, zscale: %f, %f, %f", aden->insert.xscale,
449 aden->insert.yscale, aden->insert.zscale);
450 G_debug(3, " rotang: %f", aden->insert.rotang);
451 G_debug(3, " ncols, nrows: %d, %d", aden->insert.numcols,
452 aden->insert.numrows);
453 G_debug(3, " coldist, rowdist: %f, %f", aden->insert.coldist,
454 aden->insert.rowdist);
455
456 /* write block entities */
457 adSeekBlockheader(dwghandle, aden->insert.blockheaderobjhandle,
458 adblkh);
459 if (!adblkh->purgedflag) {
460 adStartEntityGet(adblkh->entitylist);
461 while (1) {
462 ret = adGetEntity(adblkh->entitylist, adenhd2, aden2);
463 if (adenhd2->enttype == AD_ENT_ENDBLK)
464 break;
465 if (ret) {
466 /* Set transformation for lower level */
467 Trans[level + 1].dx = aden->insert.pt0[0];
468 Trans[level + 1].dy = aden->insert.pt0[1];
469 Trans[level + 1].dz = aden->insert.pt0[2];
470 Trans[level + 1].xscale = aden->insert.xscale;
471 Trans[level + 1].yscale = aden->insert.yscale;
472 Trans[level + 1].zscale = aden->insert.zscale;
473 Trans[level + 1].rotang = aden->insert.rotang;
474 wrentity(adenhd2, aden2, level + 1, adblkh->entitylist,
475 circle_as_point);
476 }
477 }
478 }
479 break;
480
481 case AD_ENT_SEQEND: /* seqend */
482 break;
483
484 case AD_ENT_POLYLINE:
485 while (1) {
486 ret = adGetEntity(entlist, adenhd2, aden2);
487 if (ret != 1) {
488 G_warning("Cannot get entity: %d: %s.", adError(),
489 adErrorStr(adError()));
490 break;
491 }
492
493 if (adenhd2->enttype == AD_ENT_SEQEND)
494 break;
495 if (adenhd2->enttype != AD_ENT_VERTEX) {
496 getEntTypeName(adenhd2, buf);
497 G_warning("Expected VERTEX got %s in POLYLINE -> skip", buf);
498 }
499 else {
500 Vect_append_point(Points, aden2->vertex.pt0[0],
501 aden2->vertex.pt0[1], aden2->vertex.pt0[2]);
502 }
503 };
504 if ((!invert_flag->answer && layer_found) ||
505 (invert_flag->answer && !layer_found))
506 write_line(adenhd, GV_LINE, level);
507 break;
508
509 default:
510 if (adenhd->enttype == adLwplineEnttype(dwghandle)) {
511 G_debug(3, "Npoints: %ld\n", aden->lwpline.numpoints);
512 bcptr = adStartBlobRead(aden->lwpline.ldblob);
513 for (il = 0; il < aden->lwpline.numpoints; il++) {
514 adReadBlob2Double(bcptr, tempdouble);
515 Vect_append_point(Points, tempdouble[0], tempdouble[1],
516 tempdouble[2]);
517 tempbulge = tempwidth[0] = tempwidth[1] = tempwidth[2] = 0.0;
518 if (aden->lwpline.flag & AD_LWPLINE_HAS_BULGES) {
519 adReadBlobDouble(bcptr, &tempbulge);
520 }
521 if (aden->lwpline.flag & AD_LWPLINE_HAS_WIDTHS) {
522 adReadBlob2Double(bcptr, tempwidth);
523 }
524 }
525 G_debug(3, "flag = %d", aden->lwpline.flag);
526 if (aden->lwpline.flag & AD_LWPLINE_IS_CLOSED) {
527 G_debug(3, " -> is closed");
528 Vect_append_point(Points, Points->x[0], Points->y[0],
529 Points->z[0]);
530 }
531 write_line(adenhd, GV_LINE, level);
532 adEndBlobRead(bcptr);
533 }
534 else {
535 getEntTypeName(adenhd, buf);
536 G_warning("%s entity not supported", buf);
537 }
538 break;
539
540 } /* end of switch */
541
542 G_free(aden2);
543 G_free(adenhd2);
544 }
545