Example #1
0
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);
}
Example #2
0
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);
}