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-2008 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 #define AD_PROTOTYPES
28 #define AD_VM_PC
29 #define OD_GENERIC_READ
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <math.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <grass/gis.h>
38 #include <grass/dbmi.h>
39 #include <grass/vector.h>
40 #include <grass/glocale.h>
41 #include "ad2.h"
42 #include "io/odio.h"
43 #include "global.h"
44 
45 int cat;
46 int n_elements;		/* number of processed elements (only low level elements) */
47 int n_skipped;		/* number of skipped low level elements (different layer name) */
48 struct Map_info Map;
49 dbDriver *driver;
50 dbString sql;
51 dbString str;
52 struct line_pnts *Points;
53 struct line_cats *Cats;
54 PAD_LAY Layer;
55 char *Txt;
56 char *Block;
57 struct field_info *Fi;
58 AD_DB_HANDLE dwghandle;
59 TRANS *Trans;		/* transformation */
60 int atrans;		/* number of allocated levels */
61 struct Option *layers_opt;
62 struct Flag *invert_flag;
63 
main(int argc,char * argv[])64 int main(int argc, char *argv[])
65 {
66     struct GModule *module;
67     struct Option *out_opt, *in_opt;
68     struct Flag *z_flag, *circle_flag, *l_flag, *int_flag;
69     char buf[2000];
70 
71     /* DWG */
72     char path[2000];
73     short initerror, entset, retval;
74     AD_OBJHANDLE pspace, mspace;
75     PAD_ENT_HDR adenhd;
76     PAD_ENT aden;
77     AD_VMADDR entlist;
78 
79     G_gisinit(argv[0]);
80 
81     module = G_define_module();
82     G_add_keyword(_("vector"));
83     G_add_keyword(_("import"));
84     module->description = _("Converts DWG/DXF to GRASS vector map");
85 
86     in_opt = G_define_standard_option(G_OPT_F_INPUT);
87     in_opt->description = _("Name of DWG or DXF file");
88 
89     out_opt = G_define_standard_option(G_OPT_V_OUTPUT);
90     out_opt->required = YES;
91 
92     layers_opt = G_define_option();
93     layers_opt->key = "layers";
94     layers_opt->type = TYPE_STRING;
95     layers_opt->required = NO;
96     layers_opt->multiple = YES;
97     layers_opt->description = _("List of layers to import");
98 
99     invert_flag = G_define_flag();
100     invert_flag->key = 'i';
101     invert_flag->description =
102 	_("Invert selection by layers (don't import layers in list)");
103 
104     z_flag = G_define_flag();
105     z_flag->key = 'z';
106     z_flag->description = _("Create 3D vector map");
107 
108     circle_flag = G_define_flag();
109     circle_flag->key = 'c';
110     circle_flag->description = _("Write circles as points (centre)");
111 
112     l_flag = G_define_flag();
113     l_flag->key = 'l';
114     l_flag->description = _("List available layers and exit");
115 
116     int_flag = G_define_flag();
117     int_flag->key = 'n';
118     int_flag->description = _("Use numeric type for attribute \"layer\"");
119 
120     if (G_parser(argc, argv))
121 	exit(EXIT_FAILURE);
122 
123     db_init_string(&sql);
124     db_init_string(&str);
125     adenhd = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR));
126     aden = (PAD_ENT) G_malloc(sizeof(AD_ENT));
127     Layer = (PAD_LAY) G_malloc(sizeof(AD_LAY));
128     Points = Vect_new_line_struct();
129     Cats = Vect_new_cats_struct();
130     Block = NULL;
131 
132     atrans = 20;		/* nested, recursive levels */
133     Trans = (TRANS *) G_malloc(atrans * sizeof(TRANS));
134 
135     /* Init OpenDWG */
136     sprintf(path, "%s/etc/adinit.dat", G_gisbase());
137     if (!adInitAd2(path, &initerror)) {
138 	sprintf(buf, _("Unable to initialize OpenDWG Toolkit, error: %d: %s."),
139 		initerror, adErrorStr(initerror));
140 	if (initerror == AD_UNABLE_TO_OPEN_INIT_FILE)
141 	    sprintf(buf, _("%s Cannot open %s"), buf, path);
142 	G_fatal_error(buf);
143     }
144     adSetupDwgRead();
145     adSetupDxfRead();
146 
147     /* Open input file */
148     if ((dwghandle = adLoadFile(in_opt->answer, AD_PRELOAD_ALL, 1)) == NULL) {
149 	G_fatal_error(_("Unable to open input file <%s>. Error %d: %s"),
150 		      in_opt->answer, adError(),
151 		      adErrorStr(adError()));
152     }
153 
154     if (l_flag->answer) {	/* List layers */
155 	PAD_TB adtb;
156 	AD_DWGHDR adhd;
157 	int i;
158 	char on, frozen, vpfrozen, locked;
159 
160 	adtb = (PAD_TB) G_malloc(sizeof(AD_TB));
161 
162 	G_debug(2, "%d layers", (int)adNumLayers(dwghandle));
163 	adReadHeaderBlock(dwghandle, &adhd);
164 	adStartLayerGet(dwghandle);
165 
166 	fprintf(stdout, "%d layers:\n", (int)adNumLayers(dwghandle));
167 	for (i = 0; i < (int)adNumLayers(dwghandle); i++) {
168 	    adGetLayer(dwghandle, &(adtb->lay));
169 	    if (!adtb->lay.purgedflag) {
170 		fprintf(stdout, "%s COLOR %d, ", adtb->lay.name,
171 			adtb->lay.color);
172 	    }
173 	    adGetLayerState(dwghandle, adtb->lay.objhandle, &on, &frozen,
174 			    &vpfrozen, &locked);
175 	    if (on)
176 		fprintf(stdout, "ON, ");
177 	    else
178 		fprintf(stdout, "OFF, ");
179 	    if (frozen)
180 		fprintf(stdout, "FROZEN, ");
181 	    else
182 		fprintf(stdout, "THAWED, ");
183 	    if (vpfrozen)
184 		fprintf(stdout, "VPFROZEN, ");
185 	    else
186 		fprintf(stdout, "VPTHAWED, ");
187 	    if (locked)
188 		fprintf(stdout, "LOCKED\n");
189 	    else
190 		fprintf(stdout, "UNLOCKED\n");
191 	}
192 	adCloseFile(dwghandle);
193 	adCloseAd2();
194 	exit(EXIT_SUCCESS);
195     }
196 
197 
198     /* open output vector */
199     if (Vect_open_new(&Map, out_opt->answer, z_flag->answer) < 0)
200 	G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer);
201 
202     Vect_hist_command(&Map);
203 
204     /* Add DB link */
205     Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE);
206     Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database,
207 			Fi->driver);
208 
209     driver =
210 	db_start_driver_open_database(Fi->driver,
211 				      Vect_subst_var(Fi->database, &Map));
212     if (driver == NULL) {
213 	G_fatal_error(_("Unable to open database <%s> by driver <%s>"),
214 		      Vect_subst_var(Fi->database, &Map), Fi->driver);
215     }
216     db_set_error_handler_driver(driver);
217 
218     db_begin_transaction(driver);
219 
220     /* Create table */
221     if (int_flag->answer) {	/* List layers */
222 	sprintf(buf,
223 		"create table %s ( cat integer, entity_name varchar(20), color int, weight int, "
224 		"layer real, block varchar(100), txt varchar(100) )",
225 		Fi->table);
226 
227     }
228     else {
229 	sprintf(buf,
230 		"create table %s ( cat integer, entity_name varchar(20), color int, weight int, "
231 		"layer varchar(100), block varchar(100), txt varchar(100) )",
232 		Fi->table);
233     }
234     db_set_string(&sql, buf);
235     G_debug(3, db_get_string(&sql));
236 
237     if (db_execute_immediate(driver, &sql) != DB_OK) {
238 	db_close_database(driver);
239 	db_shutdown_driver(driver);
240 	G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql));
241     }
242 
243     if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK)
244 	G_warning(_("Unable to create index for table <%s>, key <%s>"),
245 		  Fi->table, GV_KEY_COLUMN);
246 
247     if (db_grant_on_table
248 	(driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK)
249 	G_fatal_error(_("Unable to grant privileges on table <%s>"),
250 		      Fi->table);
251 
252     cat = 1;
253     n_elements = n_skipped = 0;
254     /* Write each entity. Some entities may be composed by other entities (like INSERT or BLOCK) */
255     /* Set transformation for first (index 0) level */
256     Trans[0].dx = Trans[0].dy = Trans[0].dz = 0;
257     Trans[0].xscale = Trans[0].yscale = Trans[0].zscale = 1;
258     Trans[0].rotang = 0;
259     if (adGetBlockHandle(dwghandle, pspace, AD_PAPERSPACE_HANDLE)) {
260 	entlist = adEntityList(dwghandle, pspace);
261 	adStartEntityGet(entlist);
262 	for (entset = 0; entset < 2; entset++) {
263 	    do {
264 		if (!(retval = adGetEntity(entlist, adenhd, aden)))
265 		    continue;
266 		wrentity(adenhd, aden, 0, entlist, circle_flag->answer);
267 	    } while (retval == 1);
268 	    if (entset == 0) {
269 		if (adGetBlockHandle(dwghandle, mspace, AD_MODELSPACE_HANDLE)) {
270 		    entlist = adEntityList(dwghandle, mspace);
271 		    adStartEntityGet(entlist);
272 		}
273 	    }
274 	}
275     }
276 
277     db_commit_transaction(driver);
278     db_close_database_shutdown_driver(driver);
279 
280     adCloseFile(dwghandle);
281     adCloseAd2();
282 
283     Vect_build(&Map, stderr);
284     Vect_close(&Map);
285 
286     if (n_skipped > 0)
287 	G_message(_("%d elements skipped (layer name was not in list)"),
288 		  n_skipped);
289 
290     G_done_msg(_("%d elements processed"), n_elements);
291 
292     exit(EXIT_SUCCESS);
293 }
294