void wrentity(PAD_ENT_HDR adenhd, PAD_ENT aden, int level, AD_VMADDR entlist, int circle_as_point) { short ret; PAD_BLOB_CTRL bcptr; PAD_ENT_HDR adenhd2; PAD_ENT aden2; OdaLong il; double tempdouble[2], tempbulge, tempwidth[2]; double x, y, z, ang; PAD_BLKH adblkh; int layer_found = 1; if (is_low_level(adenhd)) n_elements++; /* Check layer name */ if (layers_opt->answers) { int i = 0; adSeekLayer(dwghandle, adenhd->entlayerobjhandle, Layer); layer_found = 0; if (!Layer->purgedflag) { while (layers_opt->answers[i]) { if (strcmp(Layer->name, layers_opt->answers[i]) == 0) { layer_found = 1; break; } i++; } } if ((!invert_flag->answer && !layer_found) || (invert_flag->answer && layer_found)) { if (is_low_level(adenhd)) n_skipped++; if (adenhd->enttype != AD_ENT_INSERT && adenhd->enttype != AD_ENT_POLYLINE) return; } } getEntTypeName(adenhd, buf); G_debug(1, "Entity: %s", buf); Txt = NULL; adenhd2 = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR)); aden2 = (PAD_ENT) G_malloc(sizeof(AD_ENT)); adblkh = (PAD_BLKH) G_malloc(sizeof(AD_BLKH)); Vect_reset_line(Points); /* Check space for lower level */ if (level + 1 == atrans) { atrans += 10; Trans = (TRANS *) G_realloc(Trans, atrans * sizeof(TRANS)); } switch (adenhd->enttype) { case AD_ENT_LINE: Vect_append_point(Points, aden->line.pt0[0], aden->line.pt0[1], aden->line.pt0[2]); Vect_append_point(Points, aden->line.pt1[0], aden->line.pt1[1], aden->line.pt1[2]); write_line(adenhd, GV_LINE, level); break; case AD_ENT_FACE3D: Vect_append_point(Points, aden->face3d.pt0[0], aden->face3d.pt0[1], aden->face3d.pt0[2]); Vect_append_point(Points, aden->face3d.pt1[0], aden->face3d.pt1[1], aden->face3d.pt1[2]); Vect_append_point(Points, aden->face3d.pt2[0], aden->face3d.pt2[1], aden->face3d.pt2[2]); Vect_append_point(Points, aden->face3d.pt3[0], aden->face3d.pt3[1], aden->face3d.pt3[2]); write_line(adenhd, GV_FACE, level); break; case AD_ENT_SOLID: Vect_append_point(Points, aden->solid.pt0[0], aden->solid.pt0[1], aden->solid.pt0[2]); Vect_append_point(Points, aden->solid.pt1[0], aden->solid.pt1[1], aden->solid.pt1[2]); Vect_append_point(Points, aden->solid.pt2[0], aden->solid.pt2[1], aden->solid.pt2[2]); Vect_append_point(Points, aden->solid.pt3[0], aden->solid.pt3[1], aden->solid.pt3[2]); write_line(adenhd, GV_FACE, level); break; case AD_ENT_TEXT: Txt = aden->text.textstr; Vect_append_point(Points, aden->text.pt0[0], aden->text.pt0[1], aden->line.pt0[2]); write_line(adenhd, GV_POINT, level); break; case AD_ENT_POINT: Vect_append_point(Points, aden->point.pt0[0], aden->point.pt0[1], aden->line.pt0[2]); write_line(adenhd, GV_POINT, level); break; case AD_ENT_ARC: for (ang = aden->arc.stang; ang < aden->arc.endang; ang += 2 * LOCPI / 360) { x = aden->arc.pt0[0] + aden->arc.radius * cos(ang); y = aden->arc.pt0[1] + aden->arc.radius * sin(ang); z = aden->arc.pt0[2]; Vect_append_point(Points, x, y, z); } x = aden->arc.pt0[0] + aden->arc.radius * cos(aden->arc.endang); y = aden->arc.pt0[1] + aden->arc.radius * sin(aden->arc.endang); z = aden->arc.pt0[2]; Vect_append_point(Points, x, y, z); write_line(adenhd, GV_LINE, level); break; case AD_ENT_CIRCLE: if (circle_as_point) { Vect_append_point(Points, aden->circle.pt0[0], aden->circle.pt0[1], aden->circle.pt0[3]); write_line(adenhd, GV_POINT, level); } else { for (ang = 0; ang < 2 * LOCPI; ang += 2 * LOCPI / 360) { x = aden->circle.pt0[0] + aden->circle.radius * cos(ang); y = aden->circle.pt0[1] + aden->circle.radius * sin(ang); z = aden->circle.pt0[3]; Vect_append_point(Points, x, y, z); } Vect_append_point(Points, Points->x[0], Points->y[0], Points->z[0]); write_line(adenhd, GV_LINE, level); } break; /* BLOCK starts block of entities but makes no transformation - is it right ? * -> do nothing just warn for xref */ case AD_ENT_BLOCK: if (aden->block.xrefpath[0]) { G_warning ("External reference for block not supported.\n xref: %s", aden->block.xrefpath); } Block = G_store(aden->block.name2); break; case AD_ENT_ENDBLK: /* endblk - no data */ G_free(Block); Block = NULL; break; case AD_ENT_INSERT: /* insert */ /* get transformation */ /* TODO: fix rotation for CIRCLE and ARC */ G_debug(3, " x,y,z: %f, %f, %f", aden->insert.pt0[0], aden->insert.pt0[1], aden->insert.pt0[2]); G_debug(3, " xscale, yscale, zscale: %f, %f, %f", aden->insert.xscale, aden->insert.yscale, aden->insert.zscale); G_debug(3, " rotang: %f", aden->insert.rotang); G_debug(3, " ncols, nrows: %d, %d", aden->insert.numcols, aden->insert.numrows); G_debug(3, " coldist, rowdist: %f, %f", aden->insert.coldist, aden->insert.rowdist); /* write block entities */ adSeekBlockheader(dwghandle, aden->insert.blockheaderobjhandle, adblkh); if (!adblkh->purgedflag) { adStartEntityGet(adblkh->entitylist); while (1) { ret = adGetEntity(adblkh->entitylist, adenhd2, aden2); if (adenhd2->enttype == AD_ENT_ENDBLK) break; if (ret) { /* Set transformation for lower level */ Trans[level + 1].dx = aden->insert.pt0[0]; Trans[level + 1].dy = aden->insert.pt0[1]; Trans[level + 1].dz = aden->insert.pt0[2]; Trans[level + 1].xscale = aden->insert.xscale; Trans[level + 1].yscale = aden->insert.yscale; Trans[level + 1].zscale = aden->insert.zscale; Trans[level + 1].rotang = aden->insert.rotang; wrentity(adenhd2, aden2, level + 1, adblkh->entitylist, circle_as_point); } } } break; case AD_ENT_SEQEND: /* seqend */ break; case AD_ENT_POLYLINE: while (1) { ret = adGetEntity(entlist, adenhd2, aden2); if (ret != 1) { G_warning("Cannot get entity: %d: %s.", adError(), adErrorStr(adError())); break; } if (adenhd2->enttype == AD_ENT_SEQEND) break; if (adenhd2->enttype != AD_ENT_VERTEX) { getEntTypeName(adenhd2, buf); G_warning("Expected VERTEX got %s in POLYLINE -> skip", buf); } else { Vect_append_point(Points, aden2->vertex.pt0[0], aden2->vertex.pt0[1], aden2->vertex.pt0[2]); } }; if ((!invert_flag->answer && layer_found) || (invert_flag->answer && !layer_found)) write_line(adenhd, GV_LINE, level); break; default: if (adenhd->enttype == adLwplineEnttype(dwghandle)) { G_debug(3, "Npoints: %ld\n", aden->lwpline.numpoints); bcptr = adStartBlobRead(aden->lwpline.ldblob); for (il = 0; il < aden->lwpline.numpoints; il++) { adReadBlob2Double(bcptr, tempdouble); Vect_append_point(Points, tempdouble[0], tempdouble[1], tempdouble[2]); tempbulge = tempwidth[0] = tempwidth[1] = tempwidth[2] = 0.0; if (aden->lwpline.flag & AD_LWPLINE_HAS_BULGES) { adReadBlobDouble(bcptr, &tempbulge); } if (aden->lwpline.flag & AD_LWPLINE_HAS_WIDTHS) { adReadBlob2Double(bcptr, tempwidth); } } G_debug(3, "flag = %d", aden->lwpline.flag); if (aden->lwpline.flag & AD_LWPLINE_IS_CLOSED) { G_debug(3, " -> is closed"); Vect_append_point(Points, Points->x[0], Points->y[0], Points->z[0]); } write_line(adenhd, GV_LINE, level); adEndBlobRead(bcptr); } else { getEntTypeName(adenhd, buf); G_warning("%s entity not supported", buf); } break; } /* end of switch */ G_free(aden2); G_free(adenhd2); }
int main(int argc, char *argv[]) { struct GModule *module; struct Option *out_opt, *in_opt; struct Flag *z_flag, *circle_flag, *l_flag, *int_flag; char buf[2000]; /* DWG */ char path[2000]; short initerror, entset, retval; AD_OBJHANDLE pspace, mspace; PAD_ENT_HDR adenhd; PAD_ENT aden; AD_VMADDR entlist; G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("vector")); G_add_keyword(_("import")); module->description = _("Converts DWG/DXF to GRASS vector map"); in_opt = G_define_standard_option(G_OPT_F_INPUT); in_opt->description = _("Name of DWG or DXF file"); out_opt = G_define_standard_option(G_OPT_V_OUTPUT); out_opt->required = YES; layers_opt = G_define_option(); layers_opt->key = "layers"; layers_opt->type = TYPE_STRING; layers_opt->required = NO; layers_opt->multiple = YES; layers_opt->description = _("List of layers to import"); invert_flag = G_define_flag(); invert_flag->key = 'i'; invert_flag->description = _("Invert selection by layers (don't import layers in list)"); z_flag = G_define_flag(); z_flag->key = 'z'; z_flag->description = _("Create 3D vector map"); circle_flag = G_define_flag(); circle_flag->key = 'c'; circle_flag->description = _("Write circles as points (centre)"); l_flag = G_define_flag(); l_flag->key = 'l'; l_flag->description = _("List available layers and exit"); int_flag = G_define_flag(); int_flag->key = 'n'; int_flag->description = _("Use numeric type for attribute \"layer\""); if (G_parser(argc, argv)) exit(EXIT_FAILURE); db_init_string(&sql); db_init_string(&str); adenhd = (PAD_ENT_HDR) G_malloc(sizeof(AD_ENT_HDR)); aden = (PAD_ENT) G_malloc(sizeof(AD_ENT)); Layer = (PAD_LAY) G_malloc(sizeof(AD_LAY)); Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); Block = NULL; atrans = 20; /* nested, recursive levels */ Trans = (TRANS *) G_malloc(atrans * sizeof(TRANS)); /* Init OpenDWG */ sprintf(path, "%s/etc/adinit.dat", G_gisbase()); if (!adInitAd2(path, &initerror)) { sprintf(buf, _("Unable to initialize OpenDWG Toolkit, error: %d: %s."), initerror, adErrorStr(initerror)); if (initerror == AD_UNABLE_TO_OPEN_INIT_FILE) sprintf(buf, _("%s Cannot open %s"), buf, path); G_fatal_error(buf); } adSetupDwgRead(); adSetupDxfRead(); /* Open input file */ if ((dwghandle = adLoadFile(in_opt->answer, AD_PRELOAD_ALL, 1)) == NULL) { G_fatal_error(_("Unable to open input file <%s>. Error %d: %s"), in_opt->answer, adError(), adErrorStr(adError())); } if (l_flag->answer) { /* List layers */ PAD_TB adtb; AD_DWGHDR adhd; int i; char on, frozen, vpfrozen, locked; adtb = (PAD_TB) G_malloc(sizeof(AD_TB)); G_debug(2, "%d layers", (int)adNumLayers(dwghandle)); adReadHeaderBlock(dwghandle, &adhd); adStartLayerGet(dwghandle); fprintf(stdout, "%d layers:\n", (int)adNumLayers(dwghandle)); for (i = 0; i < (int)adNumLayers(dwghandle); i++) { adGetLayer(dwghandle, &(adtb->lay)); if (!adtb->lay.purgedflag) { fprintf(stdout, "%s COLOR %d, ", adtb->lay.name, adtb->lay.color); } adGetLayerState(dwghandle, adtb->lay.objhandle, &on, &frozen, &vpfrozen, &locked); if (on) fprintf(stdout, "ON, "); else fprintf(stdout, "OFF, "); if (frozen) fprintf(stdout, "FROZEN, "); else fprintf(stdout, "THAWED, "); if (vpfrozen) fprintf(stdout, "VPFROZEN, "); else fprintf(stdout, "VPTHAWED, "); if (locked) fprintf(stdout, "LOCKED\n"); else fprintf(stdout, "UNLOCKED\n"); } adCloseFile(dwghandle); adCloseAd2(); exit(EXIT_SUCCESS); } /* open output vector */ if (Vect_open_new(&Map, out_opt->answer, z_flag->answer) < 0) G_fatal_error(_("Unable to create vector map <%s>"), out_opt->answer); Vect_hist_command(&Map); /* Add DB link */ Fi = Vect_default_field_info(&Map, 1, NULL, GV_1TABLE); Vect_map_add_dblink(&Map, 1, NULL, Fi->table, GV_KEY_COLUMN, Fi->database, Fi->driver); driver = db_start_driver_open_database(Fi->driver, Vect_subst_var(Fi->database, &Map)); if (driver == NULL) { G_fatal_error(_("Unable to open database <%s> by driver <%s>"), Vect_subst_var(Fi->database, &Map), Fi->driver); } db_set_error_handler_driver(driver); db_begin_transaction(driver); /* Create table */ if (int_flag->answer) { /* List layers */ sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer real, block varchar(100), txt varchar(100) )", Fi->table); } else { sprintf(buf, "create table %s ( cat integer, entity_name varchar(20), color int, weight int, " "layer varchar(100), block varchar(100), txt varchar(100) )", Fi->table); } db_set_string(&sql, buf); G_debug(3, db_get_string(&sql)); if (db_execute_immediate(driver, &sql) != DB_OK) { db_close_database(driver); db_shutdown_driver(driver); G_fatal_error(_("Unable to create table: '%s'"), db_get_string(&sql)); } if (db_create_index2(driver, Fi->table, GV_KEY_COLUMN) != DB_OK) G_warning(_("Unable to create index for table <%s>, key <%s>"), Fi->table, GV_KEY_COLUMN); if (db_grant_on_table (driver, Fi->table, DB_PRIV_SELECT, DB_GROUP | DB_PUBLIC) != DB_OK) G_fatal_error(_("Unable to grant privileges on table <%s>"), Fi->table); cat = 1; n_elements = n_skipped = 0; /* Write each entity. Some entities may be composed by other entities (like INSERT or BLOCK) */ /* Set transformation for first (index 0) level */ Trans[0].dx = Trans[0].dy = Trans[0].dz = 0; Trans[0].xscale = Trans[0].yscale = Trans[0].zscale = 1; Trans[0].rotang = 0; if (adGetBlockHandle(dwghandle, pspace, AD_PAPERSPACE_HANDLE)) { entlist = adEntityList(dwghandle, pspace); adStartEntityGet(entlist); for (entset = 0; entset < 2; entset++) { do { if (!(retval = adGetEntity(entlist, adenhd, aden))) continue; wrentity(adenhd, aden, 0, entlist, circle_flag->answer); } while (retval == 1); if (entset == 0) { if (adGetBlockHandle(dwghandle, mspace, AD_MODELSPACE_HANDLE)) { entlist = adEntityList(dwghandle, mspace); adStartEntityGet(entlist); } } } } db_commit_transaction(driver); db_close_database_shutdown_driver(driver); adCloseFile(dwghandle); adCloseAd2(); Vect_build(&Map, stderr); Vect_close(&Map); if (n_skipped > 0) G_message(_("%d elements skipped (layer name was not in list)"), n_skipped); G_done_msg(_("%d elements processed"), n_elements); exit(EXIT_SUCCESS); }