Exemplo n.º 1
0
/**
 *	M A I N
 *
 *	Call parse_args to handle command line arguments first, then
 *	process input.
 */
int main(int ac, char *av[])
{
    /** @struct rt_i
     * This structure contains some global state information for librt
     */
    struct rt_i *rtip;

    struct db_tree_state init_state; /* state table for the hierarchy walker */
    char idbuf[1024] = {0};		/* Database title */
    int arg_count;
    char *tmp_basename;

    /** @struct user_data
     * This is an example structure.
     * It contains anything you want to have available in the region/leaf processing routines
     */
    struct user_data {
	int stuff;
    } user_data;


    arg_count = parse_args(ac, av);

    if ((ac - arg_count) < 1) {
	tmp_basename = bu_basename(av[0]);
	usage(tmp_basename, "bad argument count");
	bu_free(tmp_basename, "tmp_basename free");
    }

    /*
     *  Build an index of what's in the database.
     *  rt_dirbuild() returns an "instance" pointer which describes
     *  the database.  It also gives you back the
     *  title string in the header (ID) record.
     */
    rtip = rt_dirbuild(av[arg_count], idbuf, sizeof(idbuf));
    if (rtip == RTI_NULL) {
	bu_exit(2, "%s: rt_dirbuild failure\n", av[0]);
    }

    arg_count++;

    init_state = rt_initial_tree_state;
    db_walk_tree(rtip->rti_dbip, /* database instance */
		 ac-arg_count,		/* number of trees to get from the database */
		 (const char **)&av[arg_count],
		 1, /* number of cpus to use */
		 &init_state,
		 region_start,
		 region_end,
		 leaf_func,
		 (genptr_t)&user_data);

    /* at this point you can do things with the geometry you have obtained */

    return 0;
}
Exemplo n.º 2
0
union tree *
gcv_bottess(int argc, const char **argv, struct db_i *dbip, struct rt_tess_tol *ttol)
{
    struct db_tree_state tree_state = rt_initial_tree_state;
    tree_state.ts_ttol = ttol;

    if (db_walk_tree(dbip, argc, argv, 1, &tree_state, NULL, gcv_bottess_region_end, nmg_booltree_leaf_tess, NULL) < 0)
	bu_log("gcv_bottess: db_walk_tree failure\n");

    return NULL;
}
static int
gcv_vrml_write(const char *path, struct db_i *vdbip, const struct gcv_opts *UNUSED(options))
{
    size_t i;
    struct plate_mode pm;
    size_t num_objects = 0;
    char **object_names = NULL;

    out_file = path;
    dbip = vdbip;
    bu_setlinebuf(stderr);

    the_model = nmg_mm();
    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    /* NOTE: For visualization purposes, in the debug plot files */
    {
	/* WTF: This value is specific to the Bradley */
	nmg_eue_dist = 2.0;
    }

    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    if ((bot_dump == 1) && (eval_all == 1)) {
	bu_log("BOT Dump and Evaluate All are mutually exclusive\n");
	return 0;
    }

    if (out_file == NULL) {
	fp_out = stdout;
	setmode(fileno(fp_out), O_BINARY);
    } else {
	if ((fp_out = fopen(out_file, "wb")) == NULL) {
	    perror("g-vrml");
	    bu_log("Cannot open %s\n", out_file);
	    return 0;
	}
    }

    fprintf(fp_out, "#VRML V2.0 utf8\n");
    fprintf(fp_out, "#Units are %s\n", units);
    /* NOTE: We may want to inquire about bounding boxes for the
     * various groups and add Viewpoints nodes that point the camera
     * to the center and orient for Top, Side, etc. Views. We will add
     * some default Material Color definitions (for thousands groups)
     * before we start defining the geometry.
     */
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_999 Material { diffuseColor 0.78 0.78 0.78 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_1999 Material { diffuseColor 0.88 0.29 0.29 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_2999 Material { diffuseColor 0.82 0.53 0.54 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_3999 Material { diffuseColor 0.39 0.89 0.00 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_4999 Material { diffuseColor 1.00 0.00 0.00 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_5999 Material { diffuseColor 0.82 0.00 0.82 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_6999 Material { diffuseColor 0.62 0.62 0.62 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_7999 Material { diffuseColor 0.49 0.49 0.49 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_8999 Material { diffuseColor 0.18 0.31 0.31 } } }\n");
    fprintf(fp_out, "Shape { appearance Appearance { material DEF Material_9999 Material { diffuseColor 0.00 0.41 0.82 } } }\n");

    /* I had hoped to create a separate sub-tree (using the Transform
     * node) for each group name argument however, it appears they are
     * all handled at the same time so I will only have one Transform
     * for the complete conversion. Later on switch nodes may be added
     * to turn on and off the groups (via ROUTE nodes).
     */
    fprintf(fp_out, "Transform {\n");
    fprintf(fp_out, "\tchildren [\n");

    pm.num_bots = 0;
    pm.num_nonbots = 0;

    if (!eval_all) {
	pm.array_size = 5;
	pm.bots = (struct rt_bot_internal **)bu_calloc(pm.array_size,
		   sizeof(struct rt_bot_internal *), "pm.bots");
    }

    /* get toplevel objects */
    {
	struct directory **results;
	db_update_nref(dbip, &rt_uniresource);
	num_objects = db_ls(dbip, DB_LS_TOPS, NULL, &results);
	object_names = db_dpv_to_argv(results);
	bu_free(results, "tops");
    }

    if (eval_all) {
	(void)db_walk_tree(dbip, num_objects, (const char **)(object_names),
	       1,		/* ncpu */
	       &tree_state,
	       0,
	       nmg_region_end,
	       nmg_booltree_leaf_tess,
	       (void *)&pm);	/* in librt/nmg_bool.c */
	goto out;
    }

    if (bot_dump) {
	(void)db_walk_tree(dbip, num_objects, (const char **)(object_names),
	       1,		/* ncpu */
	       &tree_state,
	       0,
	       do_region_end2,
	       leaf_tess2,
	       (void *)&pm);	/* in librt/nmg_bool.c */
	goto out;
    }

    for (i = 0; i < num_objects; i++) {
	struct directory *dp;

	dp = db_lookup(dbip, object_names[i], LOOKUP_QUIET);
	if (dp == RT_DIR_NULL) {
	    bu_log("Cannot find %s\n", object_names[i]);
	    continue;
	}

	/* light source must be a combination */
	if (!(dp->d_flags & RT_DIR_COMB)) {
	    continue;
	}

	fprintf(fp_out, "# Includes group %s\n", object_names[i]);

	/* walk trees selecting only light source regions */
	(void)db_walk_tree(dbip, 1, (const char **)(&object_names[i]),
			   1,			/* ncpu */
			   &tree_state,
			   select_lights,
			   do_region_end1,
			   leaf_tess1,
			   (void *)&pm);	/* in librt/nmg_bool.c */
    }

    /* Walk indicated tree(s).  Each non-light-source region will be output separately */
    (void)db_walk_tree(dbip, num_objects, (const char **)(object_names),
		       1,		/* ncpu */
		       &tree_state,
		       select_non_lights,
		       do_region_end1,
		       leaf_tess1,
		       (void *)&pm);	/* in librt/nmg_bool.c */

    /* Release dynamic storage */
    nmg_km(the_model);

    if (!eval_all) {
	bu_free(pm.bots, "pm.bots");
    }

out:
    bu_free(object_names, "object_names");

    /* Now we need to close each group set */
    fprintf(fp_out, "\t]\n}\n");

    bu_log("\nTotal of %d regions converted of %d regions attempted.\n",
	regions_converted, regions_tried);

    if (regions_converted != regions_tried) {
	bu_log("Of the %d which failed conversion, %d of these failed due to conversion error.\n",
	    regions_tried - regions_converted, bomb_cnt);
    }

    fclose(fp_out);
    bu_log("Done.\n");

    return 1;
}
Exemplo n.º 4
0
/*
 *			M A I N
 */
int
main(int argc, char **argv)
{
    char		*dot, *fig_file;
    register int	c;
    double		percent;
    int size;

    bu_setlinebuf( stderr );

    jack_tree_state = rt_initial_tree_state;	/* struct copy */
    jack_tree_state.ts_tol = &tol;
    jack_tree_state.ts_ttol = &ttol;
    jack_tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* XXX These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    rt_init_resource( &rt_uniresource, 0, NULL );

    the_model = nmg_mm();
    BU_LIST_INIT( &rt_g.rtg_vlfree );	/* for vlist macros */

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "a:dn:p:r:vx:P:X:")) != EOF) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		break;
	    case 'd':
		debug_plots = 1;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		break;
	    case 'p':		/* Prefix for Jack file names. */
		prefix = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi( bu_optarg );
		rt_g.debug = 1;	/* XXX DEBUG_ALLRAYS -- to get core dumps */
		break;
	    case 'x':
		sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.debug );
		break;
	    case 'X':
		sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.NMG_debug );
		NMG_debug = rt_g.NMG_debug;
		break;
	    default:
		bu_exit(1, usage, argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	bu_exit(1, usage, argv[0]);
    }

    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    if ((dbip = db_open(argv[0], "r")) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "ERROR: Unable to open geometry database (%s)\n", argv[0]);
    }
    if ( db_dirbuild( dbip ) ) {
	bu_exit(1, "db_dirbuild failed\n" );
    }

    /* Create .fig file name and open it. */
    size = sizeof(prefix) + sizeof(argv[0] + 4);
    fig_file = bu_malloc(size, "st");
    /* Ignore leading path name. */
    if ((dot = strrchr(argv[0], '/')) != (char *)NULL) {
	if (prefix) {
	    snprintf(fig_file, size, "%s%s", prefix, 1+dot);
	} else {
	    snprintf(fig_file, size, "%s", 1+dot);
	}
    } else {
	if (prefix)
	    snprintf(fig_file, size, "%s%s", prefix, argv[0]);
	else
	    snprintf(fig_file, size, "%s", argv[0]);
    }

    /* Get rid of any file name extension (probably .g). */
    if ((dot = strrchr(fig_file, '.')) != (char *)NULL)
	*dot = '\0';
    bu_strlcat(fig_file, ".fig", size);	/* Add required Jack suffix. */

    if ((fp_fig = fopen(fig_file, "wb")) == NULL)
	perror(fig_file);
    fprintf(fp_fig, "figure {\n");
    bu_vls_init(&base_seg);		/* .fig figure file's main segment. */

    /* Walk indicated tree(s).  Each region will be output separately */
    (void)db_walk_tree(dbip, argc-1, (const char **)(argv+1),
		       1,			/* ncpu */
		       &jack_tree_state,
		       0,			/* take all regions */
		       do_region_end,
		       nmg_booltree_leaf_tess,
		       (genptr_t)NULL);	/* in librt/nmg_bool.c */

    fprintf(fp_fig, "\troot=%s_seg.base;\n", bu_vls_addr(&base_seg));
    fprintf(fp_fig, "}\n");
    fclose(fp_fig);
    bu_free(fig_file, "st");
    bu_vls_free(&base_seg);

    percent = 0;
    if (regions_tried>0)  percent = ((double)regions_done * 100) / regions_tried;
    printf("Tried %d regions, %d converted successfully.  %g%%\n",
	   regions_tried, regions_done, percent);

    return 0;
}
Exemplo n.º 5
0
/*
 *			M A I N
 */
int
main(int argc, char **argv)
{
    register int	c;
    double		percent;

    bu_setlinebuf( stderr );

#if MEMORY_LEAK_CHECKING
    rt_g.debug |= DEBUG_MEM_FULL;
#endif
    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* XXX These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-5;
    tol.para = 1 - tol.perp;

    rt_init_resource( &rt_uniresource, 0, NULL );

    the_model = nmg_mm();
    BU_LIST_INIT( &rt_g.rtg_vlfree );	/* for vlist macros */

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "mua:n:o:r:vx:D:P:X:e:i")) != EOF) {
	switch (c) {
	    case 'm':		/* include 'usemtl' statements */
		usemtl = 1;
		break;
	    case 'u':		/* Include vertexuse normals */
		do_normals = 1;
		break;
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi( bu_optarg );
		rt_g.debug = 1;	/* XXX DEBUG_ALLRAYS -- to get core dumps */
		break;
	    case 'x':
		sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.debug );
		break;
	    case 'D':
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		rt_pr_tol( &tol );
		break;
	    case 'X':
		sscanf( bu_optarg, "%x", (unsigned int *)&rt_g.NMG_debug );
		NMG_debug = rt_g.NMG_debug;
		break;
	    case 'e':		/* Error file name. */
		error_file = bu_optarg;
		break;
	    case 'i':
		inches = 1;
		break;
	    default:
		bu_exit(1, usage, argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	bu_exit(1, usage, argv[0]);
    }

    if ( !output_file )
	fp = stdout;
    else
    {
	/* Open output file */
	if ( (fp=fopen( output_file, "wb+" )) == NULL )
	{
	    perror( argv[0] );
	    bu_exit(1, "Cannot open output file (%s) for writing\n", output_file );
	}
    }

    /* Open g-obj error log file */
    if (!error_file) {
	fpe = stderr;
#if defined(_WIN32) && !defined(__CYGWIN__)
	setmode(fileno(fpe), O_BINARY);
#endif
    } else if ((fpe=fopen(error_file, "wb")) == NULL) {
	perror( argv[0] );
	bu_exit(1, "Cannot open output file (%s) for writing\n", error_file );
    }

    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    if ((dbip = db_open(argv[0], "r")) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "Unable to open geometry file (%s) for reading\n", argv[0]);
    }
    if ( db_dirbuild( dbip ) ) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    BN_CK_TOL(tree_state.ts_tol);
    RT_CK_TESS_TOL(tree_state.ts_ttol);

/* Write out  header */
    if (inches)
	fprintf(fp, "# BRL-CAD generated Wavefront OBJ file (Units in)\n");
    else
	fprintf(fp, "# BRL-CAD generated Wavefront OBJ file (Units mm)\n");

    fprintf( fp, "# BRL-CAD model: %s\n# BRL_CAD objects:", argv[0] );

    for ( c=1; c<argc; c++ )
	fprintf( fp, " %s", argv[c] );
    fprintf( fp, "\n" );

    /* Walk indicated tree(s).  Each region will be output separately */
    (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1),
			1,			/* ncpu */
			&tree_state,
			0,			/* take all regions */
			do_region_end,
			nmg_booltree_leaf_tess,
			(genptr_t)NULL);	/* in librt/nmg_bool.c */

    percent = 0;
    if (regions_tried>0) {
	percent = ((double)regions_converted * 100) / regions_tried;
	printf("Tried %d regions, %d converted to NMG's successfully.  %g%%\n",
	       regions_tried, regions_converted, percent);
    }
    percent = 0;

    if ( regions_tried > 0 ) {
	percent = ((double)regions_written * 100) / regions_tried;
	printf( "                  %d triangulated successfully. %g%%\n",
		regions_written, percent );
    }
    fclose(fp);

    /* Release dynamic storage */
    nmg_km(the_model);
    rt_vlist_cleanup();
    db_close(dbip);

#if MEMORY_LEAK_CHECKING
    bu_prmem("After complete G-ACAD conversion");
#endif

    return 0;
}
Exemplo n.º 6
0
int
main(int argc, char **argv)
{
    int	i;
    int	c;
    struct plate_mode pm;

    bu_setprogname(argv[0]);
    bu_setlinebuf( stderr );

    the_model = nmg_mm();
    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = BN_TOL_DIST;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    /* NOTE: For visualization purposes, in the debug plot files */
    {
	/* WTF: This value is specific to the Bradley */
	nmg_eue_dist = 2.0;
    }

    BU_LIST_INIT( &RTG.rtg_vlfree );	/* for vlist macros */

    BARRIER_CHECK;
    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "d:a:n:o:r:vx:P:X:u:h?")) != -1) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'd':		/* calculational tolerance */
		tol.dist = atof( bu_optarg );
		tol.dist_sq = tol.dist * tol.dist;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg)*DEG2RAD;
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name */
		out_file = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    case 'x':
		sscanf( bu_optarg, "%x", (unsigned int *)&RTG.debug );
		break;
	    case 'X':
		sscanf( bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug );
		NMG_debug = RTG.NMG_debug;
		break;
	    case 'u':
		units = bu_strdup( bu_optarg );
		scale_factor = bu_units_conversion( units );
		if ( ZERO(scale_factor) )
		    bu_exit(1, "Unrecognized units (%s)\n", units );
		scale_factor = 1.0 / scale_factor;
		break;
	    default:
		print_usage(argv[0]);
	}
    }

    if (bu_optind+1 >= argc)
	print_usage(argv[0]);

    /* Open BRL-CAD database */
    if ((dbip = db_open( argv[bu_optind], DB_OPEN_READONLY)) == DBI_NULL)
    {
	perror(argv[0]);
	bu_exit(1, "Cannot open geometry database file %s\n", argv[bu_optind] );
    }
    if ( db_dirbuild( dbip ) )
	bu_exit(1, "db_dirbuild() failed!\n" );

    if (out_file == NULL) {
	outfp = stdout;
	setmode(fileno(outfp), O_BINARY);
    } else {
	if ((outfp = fopen( out_file, "wb")) == NULL)
	{
	    perror( argv[0] );
	    bu_exit(2, "Cannot open %s\n", out_file );
	}
    }

    writeX3dHeader(outfp, out_file);
    bu_optind++;

    BARRIER_CHECK;

    pm.num_bots = 0;
    pm.num_nonbots = 0;
    pm.array_size = 5;
    pm.bots = (struct rt_bot_internal **)bu_calloc( pm.array_size,
						    sizeof( struct rt_bot_internal *), "pm.bots" );
    for ( i=bu_optind; i<argc; i++ )
    {
	struct directory *dp;

	dp = db_lookup( dbip, argv[i], LOOKUP_QUIET );
	if ( dp == RT_DIR_NULL )
	{
	    bu_log( "Cannot find %s\n", argv[i] );
	    continue;
	}

	/* light source must be a combination */
	if ( !(dp->d_flags & RT_DIR_COMB) )
	    continue;

	/* walk trees selecting only light source regions */
	(void)db_walk_tree(dbip, 1, (const char **)(&argv[i]),
			   ncpu,
			   &tree_state,
			   select_lights,
			   do_region_end,
			   leaf_tess,
			   (void *)&pm);	/* in librt/nmg_bool.c */


    }
    BARRIER_CHECK;

    /* Walk indicated tree(s).  Each non-light-source region will be output separately */
    (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]),
		       ncpu,
		       &tree_state,
		       select_non_lights,
		       do_region_end,
		       leaf_tess,
		       (void *)&pm);	/* in librt/nmg_bool.c */

    BARRIER_CHECK;
    /* Release dynamic storage */
    nmg_km(the_model);

    db_close(dbip);

    /* Now we need to close each group set */
    writeX3dEnd(outfp);

    if ( verbose )
	bu_log( "Total of %d regions converted of %d regions attempted\n",
		regions_converted, regions_tried );

    return 0;
}
Exemplo n.º 7
0
int
main(int argc, char **argv)
{
    int	i, j;
    int	c;
    double percent;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    RTG.debug = 0;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.0005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    the_model = (struct model *)NULL;
    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_m = &the_model;
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;

    rt_init_resource(&rt_uniresource, 0, NULL);

    /* For visualization purposes, in the debug plot files */
    {
	/* WTF: This value is specific to the Bradley */
	nmg_eue_dist = 2.0;
    }
    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "a:n:o:r:vx:P:X:h?")) != -1) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name */
		out_file = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		NMG_debug = RTG.NMG_debug;
		break;
	    default:
		usage(argv[0]);
	}
    }

    if (bu_optind+1 >= argc)
	usage(argv[0]);

    /* Open BRL-CAD database */
    if ((dbip = db_open(argv[bu_optind], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "Cannot open geometry database file %s\n", argv[bu_optind]);
    }
    if (db_dirbuild(dbip)) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    if (out_file == NULL) {
	fp_out = stdout;
	setmode(fileno(fp_out), O_BINARY);
    } else {
	if ((fp_out = fopen(out_file, "wb")) == NULL) {
	    bu_log("Cannot open %s\n", out_file);
	    perror(argv[0]);
	    return 2;
	}
    }
    bu_optind++;

    fprintf(fp_out, "$03");

    /* First produce an unordered list of region ident codes */
    (void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]),
		       1,			/* ncpu */
		       &tree_state,
		       get_reg_id,			/* put id in table */
		       region_stub,
		       leaf_stub,
		       (void *)NULL);

    /* Process regions in ident order */
    curr_id = 0;
    for (i = 0; i < ident_length; i++) {
	int next_id = 99999999;
	for (j = 0; j < ident_length; j++) {
	    int test_id;

	    test_id = idents[j];
	    if (test_id > curr_id && test_id < next_id)
		next_id = test_id;
	}
	curr_id = next_id;
	face_count = 0;

	bu_log("Processing id %d\n", curr_id);

	/* Walk indicated tree(s).  Each region will be output separately */

	tree_state = rt_initial_tree_state;	/* struct copy */
	the_model = nmg_mm();
	tree_state.ts_m = &the_model;
	tree_state.ts_tol = &tol;
	tree_state.ts_ttol = &ttol;

	(void)db_walk_tree(dbip, argc-bu_optind, (const char **)(&argv[bu_optind]),
			   ncpu,
			   &tree_state,
			   select_region,
			   do_region_end,
			   nmg_booltree_leaf_tess,
			   (void *)NULL);	/* in librt/nmg_bool.c */

	nmg_km(the_model);
    }

    percent = 0;
    if (regions_tried > 0)
	percent = ((double)regions_converted * 100) / regions_tried;
    printf("Tried %d regions, %d converted successfully.  %g%%\n",
	   regions_tried, regions_converted, percent);
    percent = 0;
    if (regions_tried > 0)
	percent = ((double)regions_written * 100) / regions_tried;
    printf("                  %d written successfully. %g%%\n",
	   regions_written, percent);

    /* Release dynamic storage */
    rt_vlist_cleanup();
    db_close(dbip);

    return 0;
}
Exemplo n.º 8
0
int
main(int argc, char *argv[])
{
    int verbose = 0;
    int ncpu = 1;			/* Number of processors */
    char *output_file = NULL;	/* output filename */
    struct db_i *dbip;
    struct model *the_model;
    struct rt_tess_tol ttol;		/* tessellation tolerance in mm */
    struct db_tree_state tree_state;	/* includes tol & model */

    int i, use_mc = 0, use_bottess = 0;
    struct egg_conv_data conv_data;
    struct gcv_region_end_data gcvwriter = {nmg_to_egg, NULL};

    gcvwriter.client_data = (void *)&conv_data;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &conv_data.tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    /* Set up tessellation tolerance defaults */
    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* Set up calculation tolerance defaults */
    /* FIXME: These need to be improved */
    conv_data.tol.magic = BN_TOL_MAGIC;
    conv_data.tol.dist = BN_TOL_DIST;
    conv_data.tol.dist_sq = conv_data.tol.dist * conv_data.tol.dist;
    conv_data.tol.perp = 1e-6;
    conv_data.tol.para = 1 - conv_data.tol.perp;

    conv_data.tot_polygons = 0;

    /* make empty NMG model */
    the_model = nmg_mm();
    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    /* Get command line arguments. */
    while ((i = bu_getopt(argc, argv, "a:89n:o:r:vx:D:P:X:h?")) != -1) {
	switch (i) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'D':
		conv_data.tol.dist = atof(bu_optarg);
		conv_data.tol.dist_sq = conv_data.tol.dist * conv_data.tol.dist;
		rt_pr_tol(&conv_data.tol);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		break;
	    case '8':
		use_mc = 1;
		break;
	    case '9':
		use_bottess = 1;
		break;
	    default:
		usage(argv[0]);
	}
    }

    if (bu_optind+1 >= argc)
	usage(argv[0]);

    conv_data.fp = stdout;
    if (output_file) {
	if ((conv_data.fp=fopen(output_file, "wb+")) == NULL) {
	    perror(argv[0]);
	    bu_exit(1, "Cannot open ASCII output file (%s) for writing\n", output_file);
	}
    }

    /* Open brl-cad database */
    argc -= bu_optind;
    argv += bu_optind;
    if (argc < 2 || argv[0] == NULL || argv[1] == NULL)
	usage(argv[0]);

    gcvwriter.write_region = nmg_to_egg;

    if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "Unable to open geometry database file (%s)\n", argv[0]);
    }
    if (db_dirbuild(dbip)) {
	bu_exit(1, "ERROR: db_dirbuild failed\n");
    }

    BN_CK_TOL(tree_state.ts_tol);
    RT_CK_TESS_TOL(tree_state.ts_ttol);

    if (verbose) {
	bu_log("Model: %s\n", argv[0]);
	bu_log("Objects:");
	for (i=1; i<argc; i++)
	    bu_log(" %s", argv[i]);
	bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n",
	       tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm);
	bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n",
	       tree_state.ts_tol->dist, tree_state.ts_tol->perp);
    }

    /* print the egg header stuff, including the command line to execute it */
    fprintf(conv_data.fp, "<CoordinateSystem> { Z-Up }\n\n");
    fprintf(conv_data.fp, "<Comment> {\n  \"%s", *argv);
    for (i=1; i<argc; i++)
	fprintf(conv_data.fp, " %s", argv[i]);
    fprintf(conv_data.fp, "\"\n}\n");

    /* Walk indicated tree(s).  Each region will be output separately */
    while (--argc) {
	fprintf(conv_data.fp, "<Group> %s {\n", *(argv+1));
	(void) db_walk_tree(dbip,		/* db_i */
			    1,		/* argc */
			    (const char **)(++argv), /* argv */
			    ncpu,		/* ncpu */
			    &tree_state,	/* state */
			    NULL,		/* start func */
			    use_mc?gcv_region_end_mc:use_bottess?gcv_bottess_region_end:gcv_region_end,	/* end func */
			    use_mc?NULL:nmg_booltree_leaf_tess, /* leaf func */
			    (void *)&gcvwriter);  /* client_data */
	fprintf(conv_data.fp, "}\n");
    }

    bu_log("%ld triangles written\n", conv_data.tot_polygons);

    if (output_file)
	fclose(conv_data.fp);

    /* Release dynamic storage */
    nmg_km(the_model);
    rt_vlist_cleanup();
    db_close(dbip);

    return 0;
}
int
ged_facetize(struct ged *gedp, int argc, const char *argv[])
{
    int i;
    int c;
    char *newname;
    struct rt_db_internal intern;
    struct directory *dp;
    int failed;
    int nmg_use_tnurbs = 0;
    struct db_tree_state init_state;
    struct db_i *dbip;
    union tree *facetize_tree;
    struct model *nmg_model;

    static const char *usage = "[ [-P] | [-n] [-t] [-T] ] new_obj old_obj [old_obj2 old_obj3 ...]";

    /* static due to jumping */
    static int triangulate;
    static int make_bot;
    static int marching_cube;
    static int screened_poisson;

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc < 3) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    dbip = gedp->ged_wdbp->dbip;
    RT_CHECK_DBI(dbip);

    db_init_db_tree_state(&init_state, dbip, gedp->ged_wdbp->wdb_resp);

    /* Establish tolerances */
    init_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol;
    init_state.ts_tol = &gedp->ged_wdbp->wdb_tol;

    /* Initial values for options, must be reset each time */
    marching_cube = 0;
    screened_poisson = 0;
    triangulate = 0;
    make_bot = 1;

    /* Parse options. */
    bu_optind = 1;		/* re-init bu_getopt() */
    while ((c=bu_getopt(argc, (char * const *)argv, "mntTP")) != -1) {
	switch (c) {
	    case 'm':
		marching_cube = triangulate = 1;
		/* no break, marching cubes assumes nmg for now */
	    case 'n':
		make_bot = 0;
		break;
	    case 'P':
		screened_poisson = 1;
		triangulate = 1;
		make_bot = 1;
		break;
	    case 'T':
		triangulate = 1;
		break;
	    case 't':
		nmg_use_tnurbs = 1;
		break;
	    default: {
		bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
		return GED_ERROR;
	    }
	}
    }
    argc -= bu_optind;
    argv += bu_optind;
    if (argc < 0) {
	bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
	return GED_ERROR;
    }

    if (screened_poisson && (marching_cube || !make_bot || nmg_use_tnurbs)) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    newname = (char *)argv[0];
    argv++;
    argc--;
    if (argc < 0) {
	bu_vls_printf(gedp->ged_result_str, "facetize: missing argument\n");
	return GED_ERROR;
    }

    if (db_lookup(dbip, newname, LOOKUP_QUIET) != RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "error: solid '%s' already exists, aborting\n", newname);
	return GED_ERROR;
    }

    if (screened_poisson) {

	struct rt_bot_internal *bot;

	BU_ALLOC(bot, struct rt_bot_internal);
	bot->magic = RT_BOT_INTERNAL_MAGIC;
	bot->mode = RT_BOT_SOLID;
	bot->orientation = RT_BOT_UNORIENTED;
	bot->thickness = (fastf_t *)NULL;
	bot->face_mode = (struct bu_bitv *)NULL;

	/* TODO - generate point cloud, then mesh - need to see the input points for debugging */
	(void)rt_generate_mesh(&(bot->faces), (int *)&(bot->num_faces), (point_t **)&(bot->vertices), (int *)&(bot->num_vertices),
		dbip, argv[0], 15);

	/* Export BOT as a new solid */
	RT_DB_INTERNAL_INIT(&intern);
	intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	intern.idb_type = ID_BOT;
	intern.idb_meth = &OBJ[ID_BOT];
	intern.idb_ptr = (void *) bot;

    } else {

	bu_vls_printf(gedp->ged_result_str,
		"facetize:  tessellating primitives with tolerances a=%g, r=%g, n=%g\n",
		gedp->ged_wdbp->wdb_ttol.abs, gedp->ged_wdbp->wdb_ttol.rel, gedp->ged_wdbp->wdb_ttol.norm);

	facetize_tree = (union tree *)0;
	nmg_model = nmg_mm();
	init_state.ts_m = &nmg_model;

	i = db_walk_tree(dbip, argc, (const char **)argv,
		1,
		&init_state,
		0,			/* take all regions */
		facetize_region_end,
		nmg_use_tnurbs ?
		nmg_booltree_leaf_tnurb :
		nmg_booltree_leaf_tess,
		(void *)&facetize_tree
		);


	if (i < 0) {
	    bu_vls_printf(gedp->ged_result_str, "facetize: error in db_walk_tree()\n");
	    /* Destroy NMG */
	    nmg_km(nmg_model);
	    return GED_ERROR;
	}

	if (facetize_tree) {
	    /* Now, evaluate the boolean tree into ONE region */
	    bu_vls_printf(gedp->ged_result_str, "facetize:  evaluating boolean expressions\n");

	    if (!BU_SETJUMP) {
		/* try */
		failed = nmg_boolean(facetize_tree, nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: facetization failed!!!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;

	} else
	    failed = 1;

	if (failed) {
	    bu_vls_printf(gedp->ged_result_str, "facetize:  no resulting region, aborting\n");
	    db_free_tree(facetize_tree, &rt_uniresource);
	    facetize_tree = (union tree *)NULL;
	    nmg_km(nmg_model);
	    nmg_model = (struct model *)NULL;
	    return GED_ERROR;
	}
	/* New region remains part of this nmg "model" */
	NMG_CK_REGION(facetize_tree->tr_d.td_r);
	bu_vls_printf(gedp->ged_result_str, "facetize:  %s\n", facetize_tree->tr_d.td_name);

	/* Triangulate model, if requested */
	if (triangulate && !make_bot) {
	    bu_vls_printf(gedp->ged_result_str, "facetize:  triangulating resulting object\n");
	    if (!BU_SETJUMP) {
		/* try */
		if (marching_cube == 1)
		    nmg_triangulate_model_mc(nmg_model, &gedp->ged_wdbp->wdb_tol);
		else
		    nmg_triangulate_model(nmg_model, &gedp->ged_wdbp->wdb_tol);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: triangulation failed!!!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;
	}

	if (make_bot) {
	    struct rt_bot_internal *bot;
	    struct nmgregion *r;
	    struct shell *s;

	    bu_vls_printf(gedp->ged_result_str, "facetize:  converting to BOT format\n");

	    /* WTF, FIXME: this is only dumping the first shell of the first region */

	    r = BU_LIST_FIRST(nmgregion, &nmg_model->r_hd);
	    if (r && BU_LIST_NEXT(nmgregion, &r->l) !=  (struct nmgregion *)&nmg_model->r_hd)
		bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one region, only facetizing the first\n");

	    s = BU_LIST_FIRST(shell, &r->s_hd);
	    if (s && BU_LIST_NEXT(shell, &s->l) != (struct shell *)&r->s_hd)
		bu_vls_printf(gedp->ged_result_str, "WARNING: model has more than one shell, only facetizing the first\n");

	    if (!BU_SETJUMP) {
		/* try */
		bot = (struct rt_bot_internal *)nmg_bot(s, &gedp->ged_wdbp->wdb_tol);
	    } else {
		/* catch */
		BU_UNSETJUMP;
		bu_vls_printf(gedp->ged_result_str, "WARNING: conversion to BOT failed!\n");
		db_free_tree(facetize_tree, &rt_uniresource);
		facetize_tree = (union tree *)NULL;
		nmg_km(nmg_model);
		nmg_model = (struct model *)NULL;
		return GED_ERROR;
	    } BU_UNSETJUMP;

	    nmg_km(nmg_model);
	    nmg_model = (struct model *)NULL;

	    /* Export BOT as a new solid */
	    RT_DB_INTERNAL_INIT(&intern);
	    intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    intern.idb_type = ID_BOT;
	    intern.idb_meth = &OBJ[ID_BOT];
	    intern.idb_ptr = (void *) bot;
	} else {

	    bu_vls_printf(gedp->ged_result_str, "facetize:  converting NMG to database format\n");

	    /* Export NMG as a new solid */
	    RT_DB_INTERNAL_INIT(&intern);
	    intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    intern.idb_type = ID_NMG;
	    intern.idb_meth = &OBJ[ID_NMG];
	    intern.idb_ptr = (void *)nmg_model;
	    nmg_model = (struct model *)NULL;
	}

    }

    dp=db_diradd(dbip, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&intern.idb_type);
    if (dp == RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "Cannot add %s to directory\n", newname);
	return GED_ERROR;
    }

    if (rt_db_put_internal(dp, dbip, &intern, &rt_uniresource) < 0) {
	bu_vls_printf(gedp->ged_result_str, "Failed to write %s to database\n", newname);
	rt_db_free_internal(&intern);
	return GED_ERROR;
    }

    if (!screened_poisson) {
	facetize_tree->tr_d.td_r = (struct nmgregion *)NULL;

	/* Free boolean tree, and the regions in it */
	db_free_tree(facetize_tree, &rt_uniresource);
	facetize_tree = (union tree *)NULL;
    }

    return GED_OK;
}
Exemplo n.º 10
0
int
main(int argc, char *argv[])
{
    struct user_data your_data = {0, BN_TOL_INIT_ZERO};

    int i;
    int c;
    char idbuf[132] = {0};

    struct rt_i *rtip;
    struct db_tree_state init_state;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    /* calculational tolerances
     * mostly used by NMG routines
     */
    your_data.tol.magic = BN_TOL_MAGIC;
    your_data.tol.dist = BN_TOL_DIST;
    your_data.tol.dist_sq = your_data.tol.dist * your_data.tol.dist;
    your_data.tol.perp = 1e-6;
    your_data.tol.para = 1 - your_data.tol.perp;

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "t:a:n:o:r:x:X:")) != -1) {
	switch (c) {
	    case 't':		/* calculational tolerance */
		your_data.tol.dist = atof(bu_optarg);
		your_data.tol.dist_sq = your_data.tol.dist * your_data.tol.dist;
	    case 'o':		/* Output file name */
		/* grab output file name */
		break;
	    case 'x':		/* librt debug flag */
		sscanf(bu_optarg, "%x", &RTG.debug);
		bu_printb("librt RT_G_DEBUG", RT_G_DEBUG, DEBUG_FORMAT);
		bu_log("\n");
		break;
	    case 'X':		/* NMG debug flag */
		sscanf(bu_optarg, "%x", &RTG.NMG_debug);
		bu_printb("librt RTG.NMG_debug", RTG.NMG_debug, NMG_DEBUG_FORMAT);
		bu_log("\n");
		break;
	    default:
		print_usage(argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	print_usage(argv[0]);
    }

    /* Open BRL-CAD database */
    /* Scan all the records in the database and build a directory */
    rtip=rt_dirbuild(argv[bu_optind], idbuf, sizeof(idbuf));
    if (rtip == RTI_NULL) {
	bu_exit(1, "g-xxx: rt_dirbuild failure\n");
    }

    init_state = rt_initial_tree_state;

    bu_optind++;

    /* Walk the trees named on the command line
     * outputting combinations and primitives
     */
    for (i=bu_optind; i<argc; i++) {
	db_walk_tree(rtip->rti_dbip, argc - i, (const char **)&argv[i], 1 /* bu_avail_cpus() */,
		     &init_state, region_start, region_end, primitive_func, (void *) &your_data);
    }

    return 0;
}
Exemplo n.º 11
0
/*
 * This routine is the drawable geometry object's analog of rt_gettrees().
 * Add a set of tree hierarchies to the active set.
 * Note that argv[0] should be ignored, it has the command name in it.
 *
 * Returns -
 * 0 Ordinarily
 * -1 On major error
 */
int
_ged_drawtrees(struct ged *gedp, int argc, const char *argv[], int kind, struct _ged_client_data *_dgcdp)
{
    int ret = 0;
    int c;
    int ncpu = 1;
    int nmg_use_tnurbs = 0;
    int enable_fastpath = 0;
    struct model *nmg_model;
    struct _ged_client_data dgcdp;
    int i;
    int ac = 1;
    char *av[3];

    RT_CHECK_DBI(gedp->ged_wdbp->dbip);

    if (argc <= 0)
	return -1;	/* FAIL */

    ++drawtrees_depth;
    av[1] = (char *)0;

    /* options are already parsed into _dgcdp */
    if (_dgcdp != (struct _ged_client_data *)0) {
	dgcdp = *_dgcdp;            /* struct copy */
    } else {
	struct bview *gvp;

	memset(&dgcdp, 0, sizeof(struct _ged_client_data));
	dgcdp.gedp = gedp;

	gvp = gedp->ged_gvp;
	if (gvp && gvp->gv_adaptive_plot)
	    dgcdp.autoview = 1;
	else
	    dgcdp.autoview = 0;

	/* Initial values for options, must be reset each time */
	dgcdp.draw_nmg_only = 0;	/* no booleans */
	dgcdp.nmg_triangulate = 1;
	dgcdp.draw_wireframes = 0;
	dgcdp.draw_normals = 0;
	dgcdp.draw_solid_lines_only = 0;
	dgcdp.draw_no_surfaces = 0;
	dgcdp.shade_per_vertex_normals = 0;
	dgcdp.draw_edge_uses = 0;
	dgcdp.wireframe_color_override = 0;
	dgcdp.fastpath_count = 0;
	dgcdp.shaded_mode_override = _GED_SHADED_MODE_UNSET;

	/* default color - red */
	dgcdp.wireframe_color[0] = 255;
	dgcdp.wireframe_color[1] = 0;
	dgcdp.wireframe_color[2] = 0;

	/* default transparency - opaque */
	dgcdp.transparency = 1.0;

	/* freesolid */
	dgcdp.freesolid = gedp->freesolid;

	enable_fastpath = 0;

	/* Parse options. */
	bu_optind = 0;		/* re-init bu_getopt() */
	while ((c = bu_getopt(argc, (char * const *)argv, "dfhm:nqstuvwx:C:STP:A:oR")) != -1) {
	    switch (c) {
		case 'u':
		    dgcdp.draw_edge_uses = 1;
		    break;
		case 's':
		    dgcdp.draw_solid_lines_only = 1;
		    break;
		case 't':
		    nmg_use_tnurbs = 1;
		    break;
		case 'v':
		    dgcdp.shade_per_vertex_normals = 1;
		    break;
		case 'w':
		    dgcdp.draw_wireframes = 1;
		    break;
		case 'S':
		    dgcdp.draw_no_surfaces = 1;
		    break;
		case 'T':
		    dgcdp.nmg_triangulate = 0;
		    break;
		case 'n':
		    dgcdp.draw_normals = 1;
		    break;
		case 'P':
		    ncpu = atoi(bu_optarg);
		    break;
		case 'q':
		    dgcdp.do_not_draw_nmg_solids_during_debugging = 1;
		    break;
		case 'd':
		    dgcdp.draw_nmg_only = 1;
		    break;
		case 'f':
		    enable_fastpath = 1;
		    break;
		case 'C':
		    {
			int r, g, b;
			char *cp = bu_optarg;

			r = atoi(cp);
			while ((*cp >= '0' && *cp <= '9')) cp++;
			while (*cp && (*cp < '0' || *cp > '9')) cp++;
			g = atoi(cp);
			while ((*cp >= '0' && *cp <= '9')) cp++;
			while (*cp && (*cp < '0' || *cp > '9')) cp++;
			b = atoi(cp);

			if (r < 0 || r > 255) r = 255;
			if (g < 0 || g > 255) g = 255;
			if (b < 0 || b > 255) b = 255;

			dgcdp.wireframe_color_override = 1;
			dgcdp.wireframe_color[0] = r;
			dgcdp.wireframe_color[1] = g;
			dgcdp.wireframe_color[2] = b;
		    }
		    break;
		case 'h':
		    dgcdp.hiddenLine = 1;
		    dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL;
		    break;
		case 'm':
		    dgcdp.shaded_mode_override = atoi(bu_optarg);

		    switch (dgcdp.shaded_mode_override) {
			case 0:
			    dgcdp.shaded_mode_override = _GED_WIREFRAME;
			    break;
			case 1:
			    dgcdp.shaded_mode_override = _GED_SHADED_MODE_BOTS;
			    break;
			case 2:
			    dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL;
			    break;
			case 3:
			    dgcdp.shaded_mode_override = _GED_SHADED_MODE_EVAL;
			    break;
			default:
			    if (dgcdp.shaded_mode_override < 0) {
				dgcdp.shaded_mode_override = _GED_SHADED_MODE_UNSET;
			    } else {
				dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL;
			    }
		    }
		    break;
		case 'x':
		    dgcdp.transparency = atof(bu_optarg);

		    /* clamp it to [0, 1] */
		    if (dgcdp.transparency < 0.0)
			dgcdp.transparency = 0.0;

		    if (1.0 < dgcdp.transparency)
			dgcdp.transparency = 1.0;

		    break;
		case 'R':
		    dgcdp.autoview = 0;
		    break;
		case 'A':
		case 'o':
		    /* nothing to do, handled by edit_com wrapper on the front-end */
		    break;
		default:
		    {
			bu_vls_printf(gedp->ged_result_str, "unrecognized option - %c\n", c);
			--drawtrees_depth;
			return GED_ERROR;
		    }
	    }
	}
	argc -= bu_optind;
	argv += bu_optind;

	switch (kind) {
	    case _GED_DRAW_WIREFRAME:
		dgcdp.dmode = _GED_WIREFRAME;
		if (dgcdp.shaded_mode_override != _GED_SHADED_MODE_UNSET) {
		    dgcdp.dmode = dgcdp.shaded_mode_override;
		} else if (gedp->ged_gdp->gd_shaded_mode) {
 		    dgcdp.dmode = gedp->ged_gdp->gd_shaded_mode;
		}
		break;
	    case _GED_DRAW_NMG_POLY:
		dgcdp.dmode = _GED_BOOL_EVAL;
		break;
	}

    }

    if (!argc) {
	bu_vls_printf(gedp->ged_result_str, "Please specify one or more objects to be drawn.\n");
	--drawtrees_depth;
	return -1;
    }

    switch (kind) {
	default:
	    bu_vls_printf(gedp->ged_result_str, "ERROR, bad kind\n");
	    --drawtrees_depth;
	    return -1;
	case _GED_DRAW_WIREFRAME:
	    /*
	     * If asking for wireframe and in shaded_mode and no shaded mode override,
	     * or asking for wireframe and shaded mode is being overridden with a value
	     * greater than 0, then draw shaded polygons for each object's primitives if possible.
	     *
	     * Note -
	     * If shaded_mode is _GED_SHADED_MODE_BOTS, only BOTS and polysolids
	     * will be shaded. The rest is drawn as wireframe.
	     * If shaded_mode is _GED_SHADED_MODE_ALL, everything except pipe solids
	     * are drawn as shaded polygons.
	     */
	    if (dgcdp.dmode == _GED_SHADED_MODE_BOTS ||
		dgcdp.dmode == _GED_SHADED_MODE_ALL  ||
		dgcdp.dmode == _GED_SHADED_MODE_EVAL)
	    {
		struct _ged_client_data dgcdp_save;

		for (i = 0; i < argc; ++i) {
		    if (drawtrees_depth == 1)
			dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]);

		    if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL)
			continue;

		    dgcdp_save = dgcdp;

		    if (dgcdp.dmode == _GED_SHADED_MODE_EVAL) {
			ret = plot_shaded_eval(gedp, argv[i], &dgcdp);
			if (ret == GED_OK) {
			    continue;
			}
			/* if evaluated shading failed, fall back to "all" mode */
			dgcdp.gedp->ged_gdp->gd_shaded_mode = 0;
			dgcdp.shaded_mode_override = _GED_SHADED_MODE_ALL;
			dgcdp.dmode = _GED_SHADED_MODE_ALL;
		    }

		    av[0] = (char *)argv[i];
		    ret = db_walk_tree(gedp->ged_wdbp->dbip,
				       ac,
				       (const char **)av,
				       ncpu,
				       &gedp->ged_wdbp->wdb_initial_tree_state,
				       NULL,
				       draw_check_region_end,
				       draw_check_leaf,
				       (void *)&dgcdp);

		    dgcdp = dgcdp_save;
		}
	    } else {
		struct display_list **paths_to_draw;
		struct display_list *gdlp;

		paths_to_draw = (struct display_list **)
		    bu_malloc(sizeof(struct display_list *) * argc,
		    "redraw paths");

		/* create solids */
		for (i = 0; i < argc; ++i) {
		    struct bview_client_data bview_data;
		    bview_data.draw_solid_lines_only = dgcdp.draw_solid_lines_only;
		    bview_data.wireframe_color_override = dgcdp.wireframe_color_override;
		    bview_data.wireframe_color[0]= dgcdp.wireframe_color[0];
		    bview_data.wireframe_color[1]= dgcdp.wireframe_color[1];
		    bview_data.wireframe_color[2]= dgcdp.wireframe_color[2];
		    bview_data.transparency= dgcdp.transparency;
		    bview_data.dmode = dgcdp.dmode;
		    bview_data.hiddenLine = dgcdp.hiddenLine;
		    bview_data.freesolid = (void *)gedp->freesolid;

		    dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]);
		    bview_data.gdlp = dgcdp.gdlp;

		    /* store draw path */
		    paths_to_draw[i] = dgcdp.gdlp;

		    if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL) {
			continue;
		    }

		    av[0] = (char *)argv[i];
		    ret = db_walk_tree(gedp->ged_wdbp->dbip,
				       ac,
				       (const char **)av,
				       ncpu,
				       &gedp->ged_wdbp->wdb_initial_tree_state,
				       NULL,
				       wireframe_region_end,
				       append_solid_to_display_list,
				       (void *)&bview_data);
		}

		/* We need to know the view size in order to choose
		 * appropriate input values for the adaptive plot
		 * routines. Unless we're keeping the current view,
		 * we need to autoview now so we have the correct
		 * view size for plotting.
		 */
		if (dgcdp.autoview) {
		    const char *autoview_args[2] = {"autoview", NULL};
		    ged_autoview(gedp, 1, autoview_args);
		}

		/* calculate plot vlists for solids of each draw path */
		for (i = 0; i < argc; ++i) {
		    gdlp = paths_to_draw[i];

		    if (gdlp == GED_DISPLAY_LIST_NULL) {
			continue;
		    }

		    ret = dl_redraw(gdlp, gedp->ged_wdbp->dbip, &gedp->ged_wdbp->wdb_initial_tree_state, gedp->ged_gvp, gedp->ged_create_vlist_callback);
		    if (ret < 0) {
			bu_vls_printf(gedp->ged_result_str,
				"%s: %s redraw failure\n", argv[0], argv[i]);
			return GED_ERROR;
		    }
		}

		bu_free(paths_to_draw, "draw paths");
	    }
	    break;
	case _GED_DRAW_NMG_POLY:
	    {
		nmg_model = nmg_mm();
		gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &nmg_model;
		if (dgcdp.draw_edge_uses) {
		    bu_vls_printf(gedp->ged_result_str, "Doing the edgeuse thang (-u)\n");
		    dgcdp.draw_edge_uses_vbp = rt_vlblock_init();
		}

		for (i = 0; i < argc; ++i) {
		    if (drawtrees_depth == 1)
			dgcdp.gdlp = dl_addToDisplay(gedp->ged_gdp->gd_headDisplay, gedp->ged_wdbp->dbip, argv[i]);

		    if (dgcdp.gdlp == GED_DISPLAY_LIST_NULL)
			continue;

		    av[0] = (char *)argv[i];
		    ret = db_walk_tree(gedp->ged_wdbp->dbip,
				       ac,
				       (const char **)av,
				       ncpu,
				       &gedp->ged_wdbp->wdb_initial_tree_state,
				       enable_fastpath ? draw_nmg_region_start : 0,
				       draw_nmg_region_end,
				       nmg_use_tnurbs ? nmg_booltree_leaf_tnurb : nmg_booltree_leaf_tess,
				       (void *)&dgcdp);
		}

		if (dgcdp.draw_edge_uses) {
		    _ged_cvt_vlblock_to_solids(gedp, dgcdp.draw_edge_uses_vbp, "_EDGEUSES_", 0);
		    bn_vlblock_free(dgcdp.draw_edge_uses_vbp);
		    dgcdp.draw_edge_uses_vbp = (struct bn_vlblock *)NULL;
		}

		/* Destroy NMG */
		nmg_km(nmg_model);
		break;
	    }
    }

    --drawtrees_depth;

    if (dgcdp.fastpath_count) {
	bu_log("%d region%s rendered through polygon fastpath\n",
	       dgcdp.fastpath_count, dgcdp.fastpath_count == 1 ? "" : "s");
    }

    if (ret < 0)
	return -1;

    return 0;	/* OK */
}
Exemplo n.º 12
0
int
main(int argc, char **argv)
{
    int c;
    double percent;
    int i;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    RTG.debug = 0;

    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = BN_TOL_DIST;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    the_model = nmg_mm();
    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "a:n:o:r:vx:D:P:X:e:ih?")) != -1) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'D':
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		rt_pr_tol(&tol);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		NMG_debug = RTG.NMG_debug;
		break;
	    case 'e':		/* Error file name. */
		error_file = bu_optarg;
		break;
	    case 'i':
		inches = 1;
		break;
	    default:
		usage(argv[0]);
	}
    }

    if (bu_optind+1 >= argc)
	usage(argv[0]);

    if (!output_file) {
	fp = stdout;
	setmode(fileno(fp), O_BINARY);
    } else {
	/* Open output file */
	if ((fp=fopen(output_file, "wb+")) == NULL) {
	    perror(argv[0]);
	    bu_exit(1, "Cannot open output file (%s) for writing\n", output_file);
	}
    }

    /* Open g-acad error log file */
    if (!error_file) {
	fpe = stderr;
	setmode(fileno(fpe), O_BINARY);
    } else if ((fpe=fopen(error_file, "wb")) == NULL) {
	perror(argv[0]);
	bu_exit(1, "Cannot open output file (%s) for writing\n", error_file);
    }


    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "Cannot open geometry database file (%s)\n", argv[0]);
    }
    if (db_dirbuild(dbip)) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    BN_CK_TOL(tree_state.ts_tol);
    RT_CK_TESS_TOL(tree_state.ts_ttol);

    fprintf(fpe, "Model: %s\n", argv[0]);
    fprintf(fpe, "Objects:");
    for (i=1; i<argc; i++)
	fprintf(fpe, " %s", argv[i]);
    fprintf(fpe, "\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n",
	    tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm);
    fprintf(fpe, "Calculational tolerances:\n\tdist = %g mm perp = %g\n",
	    tree_state.ts_tol->dist, tree_state.ts_tol->perp);

    bu_log("Model: %s\n", argv[0]);
    bu_log("Objects:");
    for (i=1; i<argc; i++)
	bu_log(" %s", argv[i]);
    bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n",
	   tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm);
    bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n",
	   tree_state.ts_tol->dist, tree_state.ts_tol->perp);

/* Write out ACAD facet header */
    if (inches)
	fprintf(fp, "BRL-CAD generated ACAD FACET FILE (Units in)\n");
    else
	fprintf(fp, "BRL-CAD generated ACAD FACET FILE (Units mm)\n");

/* Generate space for number of facet entities, will write over later */

    fprintf(fp, "               ");

    /* Walk indicated tree(s).  Each region will be output separately */
    (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1),
			1,			/* ncpu */
			&tree_state,
			0,			/* take all regions */
			do_region_end,
			nmg_booltree_leaf_tess,
			(void *)NULL);	/* in librt/nmg_bool.c */

    percent = 0;
    if (regions_tried>0) {
	percent = ((double)regions_converted * 100) / regions_tried;
	printf("Tried %d regions, %d converted to NMG's successfully.  %g%%\n",
	       regions_tried, regions_converted, percent);
    }
    percent = 0;

    if (regions_tried > 0) {
	percent = ((double)regions_written * 100) / regions_tried;
	printf("                  %d triangulated successfully. %g%%\n",
	       regions_written, percent);
    }

    bu_log("%ld triangles written\n", tot_polygons);
    fprintf(fpe, "%ld triangles written\n", tot_polygons);

    /* Write out number of facet entities to .facet file */

    rewind(fp);
    bu_fseek(fp, 46, 0); /* Re-position pointer to 2nd line */
    fprintf(fp, "%d\n", regions_written); /* Write out number of regions */
    fclose(fp);

    /* Release dynamic storage */
    nmg_km(the_model);
    rt_vlist_cleanup();
    db_close(dbip);

    return 0;
}
Exemplo n.º 13
0
/**
 * This is the gist for what is going on (not verified):
 *
 * 1. initialize tree_state (db_tree_state)
 * 2. Deal with command line arguments. Strip off everything but regions for processing.
 * 3. Open geometry (.g) file and build directory db_dirbuild
 * 4. db_walk_tree (get_layer) for layer names only
 * 5. Initialize tree_state
 * 6. Initialize model (nmg)\
 * 7. db_walk_tree (gcv_region_end)
 * 8. Cleanup
 */
int
main(int argc, char *argv[])
{
    int c;
    double percent;

    bu_setlinebuf(stderr);

    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    /* Set up tessellation tolerance defaults */
    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* Set up calculation tolerance defaults */
    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.0005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    /* init resources we might need */
    rt_init_resource(&rt_uniresource, 0, NULL);

    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "a:n:o:pr:vx:D:P:X:ih?")) != -1) {
	switch (c) {
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'p':
		polyface_mesh = 1;
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'v':
		verbose++;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'D':
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		rt_pr_tol(&tol);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		NMG_debug = RTG.NMG_debug;
		break;
	    case 'i':
		inches = 1;
		break;
	    default:
		usage(argv[0]);
		bu_exit(1, "%s\n", brlcad_ident("BRL-CAD to DXF Exporter"));
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	usage(argv[0]);
	bu_exit(1, "%s\n", brlcad_ident("BRL-CAD to DXF Exporter"));
    }

    if (!output_file) {
	fp = stdout;
	setmode(fileno(fp), O_BINARY);
    } else {
	/* Open output file */
	if ((fp=fopen(output_file, "w+b")) == NULL) {
	    perror(argv[0]);
	    bu_exit(1, " Cannot open output file (%s) for writing\n", output_file);
	}
    }

    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "Unable to open geometry database file (%s)\n", argv[0]);
    }

    if (db_dirbuild(dbip)) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    BN_CK_TOL(tree_state.ts_tol);
    RT_CK_TESS_TOL(tree_state.ts_ttol);

    if (verbose) {
	int i;

	bu_log("Model: %s\n", argv[0]);
	bu_log("Objects:");
	for (i = 1; i < argc; i++)
	    bu_log(" %s", argv[i]);
	bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n",
		tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm);
	bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n",
		tree_state.ts_tol->dist, tree_state.ts_tol->perp);
    }

    /* output DXF header and start of TABLES section */
    fprintf(fp,
	    "0\nSECTION\n2\nHEADER\n999\n%s\n0\nENDSEC\n0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nLAYER\n",
	    argv[argc-1]);

    /* Walk indicated tree(s) just for layer names to put in TABLES section */
    (void)db_walk_tree(dbip, argc-1, (const char **)(argv+1),
		       1,			/* ncpu */
		       &tree_state,
		       0,			/* take all regions */
		       get_layer,
		       NULL,
		       (void *)NULL);	/* in librt/nmg_bool.c */

    /* end of layers section, start of ENTITIES SECTION */
    fprintf(fp, "0\nENDTAB\n0\nENDSEC\n0\nSECTION\n2\nENTITIES\n");

    /* Walk indicated tree(s).  Each region will be output separately */
    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    /* make empty NMG model */
    the_model = nmg_mm();
    tree_state.ts_m = &the_model;
    (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1),
			1,			/* ncpu */
			&tree_state,
			0,			/* take all regions */
			gcv_region_end,
			nmg_booltree_leaf_tess,
			(void *)&gcvwriter);	/* callback for gcv_region_end */

    percent = 0;
    if (regions_tried>0) {
	percent = ((double)regions_converted * 100) / regions_tried;
	if (verbose)
	    bu_log("Tried %d regions, %d converted to NMG's successfully.  %g%%\n",
		   regions_tried, regions_converted, percent);
    }
    percent = 0;

    if (regions_tried > 0) {
	percent = ((double)regions_written * 100) / regions_tried;
	if (verbose)
	    bu_log("                  %d triangulated successfully. %g%%\n",
		    regions_written, percent);
    }

    bu_log("%ld triangles written\n", (long int)tot_polygons);

    fprintf(fp, "0\nENDSEC\n0\nEOF\n");

    if (output_file) {
	fclose(fp);
    }

    /* Release dynamic storage */
    nmg_km(the_model);
    rt_vlist_cleanup();
    db_close(dbip);

    return 0;
}
Exemplo n.º 14
0
int
ged_bev(struct ged *gedp, int argc, const char *argv[])
{
    static const char *usage = "[P|t] new_obj obj1 op obj2 op obj3 ...";

    int i;
    int c;
    int ncpu;
    char *cmdname;
    char *newname;
    struct rt_db_internal intern;
    struct directory *dp;
    char op;
    int failed;

    /* static due to longjmp */
    static int triangulate = 0;
    static union tree *tmp_tree = NULL;

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_READ_ONLY(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc < 3) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    cmdname = (char *)argv[0];

    /* Establish tolerances */
    gedp->ged_wdbp->wdb_initial_tree_state.ts_ttol = &gedp->ged_wdbp->wdb_ttol;
    gedp->ged_wdbp->wdb_initial_tree_state.ts_tol = &gedp->ged_wdbp->wdb_tol;

    gedp->ged_wdbp->wdb_ttol.magic = RT_TESS_TOL_MAGIC;

    /* Initial values for options, must be reset each time */
    ncpu = 1;
    triangulate = 0;

    /* Parse options. */
    bu_optind = 1;		/* re-init bu_getopt() */
    while ((c=bu_getopt(argc, (char * const *)argv, "tP:")) != -1) {
	switch (c) {
	    case 'P':
#if 0
		/* not yet supported */
		ncpu = atoi(bu_optarg);
#endif
		break;
	    case 't':
		triangulate = 1;
		break;
	    default: {
		bu_vls_printf(gedp->ged_result_str, "%s: option '%c' unknown\n", cmdname, c);
	    }

		break;
	}
    }
    argc -= bu_optind;
    argv += bu_optind;

    newname = (char *)argv[0];
    argv++;
    argc--;

    if (argc < 1) {
	bu_vls_printf(gedp->ged_result_str, "%s: Nothing to evaluate!!!\n", cmdname);
	return GED_ERROR;
    }

    GED_CHECK_EXISTS(gedp, newname, LOOKUP_QUIET, GED_ERROR);

    bu_vls_printf(gedp->ged_result_str,
		  "%s:  tessellating primitives with tolerances a=%g, r=%g, n=%g\n",
		  argv[0],
		  gedp->ged_wdbp->wdb_ttol.abs,
		  gedp->ged_wdbp->wdb_ttol.rel,
		  gedp->ged_wdbp->wdb_ttol.norm);

    bev_facetize_tree = (union tree *)0;
    bev_nmg_model = nmg_mm();
    gedp->ged_wdbp->wdb_initial_tree_state.ts_m = &bev_nmg_model;

    op = ' ';
    tmp_tree = (union tree *)NULL;

    while (argc) {
	i = db_walk_tree(gedp->ged_wdbp->dbip, 1, (const char **)argv,
			 ncpu,
			 &gedp->ged_wdbp->wdb_initial_tree_state,
			 0,			/* take all regions */
			 bev_facetize_region_end,
			 nmg_booltree_leaf_tess,
			 (genptr_t)gedp);

	if (i < 0) {
	    bu_vls_printf(gedp->ged_result_str, "%s: error in db_walk_tree()\n", cmdname);
	    /* Destroy NMG */
	    nmg_km(bev_nmg_model);
	    return GED_ERROR;
	}
	argc--;
	argv++;

	if (tmp_tree && op != ' ') {
	    union tree *new_tree;

	    BU_ALLOC(new_tree, union tree);
	    RT_TREE_INIT(new_tree);

	    new_tree->tr_b.tb_regionp = REGION_NULL;
	    new_tree->tr_b.tb_left = tmp_tree;
	    new_tree->tr_b.tb_right = bev_facetize_tree;

	    switch (op) {
		case 'u':
		case 'U':
		    new_tree->tr_op = OP_UNION;
		    break;
		case '-':
		    new_tree->tr_op = OP_SUBTRACT;
		    break;
		case '+':
		    new_tree->tr_op = OP_INTERSECT;
		    break;
		default: {
		    bu_vls_printf(gedp->ged_result_str, "%s: Unrecognized operator: (%c)\nAborting\n",
				  argv[0], op);
		    db_free_tree(bev_facetize_tree, &rt_uniresource);
		    nmg_km(bev_nmg_model);
		    return GED_ERROR;
		}
	    }

	    tmp_tree = new_tree;
	    bev_facetize_tree = (union tree *)NULL;
	} else if (!tmp_tree && op == ' ') {
	    /* just starting out */
	    tmp_tree = bev_facetize_tree;
	    bev_facetize_tree = (union tree *)NULL;
	}

	if (argc) {
	    op = *argv[0];
	    argc--;
	    argv++;
	} else
	    op = ' ';

    }

    if (tmp_tree) {
	/* Now, evaluate the boolean tree into ONE region */
	bu_vls_printf(gedp->ged_result_str, "%s: evaluating boolean expressions\n", cmdname);

	if (BU_SETJUMP) {
	    BU_UNSETJUMP;

	    bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Boolean evaluation failed!!!\n", cmdname);
	    if (tmp_tree)
		db_free_tree(tmp_tree, &rt_uniresource);
	    tmp_tree = (union tree *)NULL;
	    nmg_km(bev_nmg_model);
	    bev_nmg_model = (struct model *)NULL;
	    return GED_ERROR;
	}

	failed = nmg_boolean(tmp_tree, bev_nmg_model, &gedp->ged_wdbp->wdb_tol, &rt_uniresource);
	BU_UNSETJUMP;
    } else
	failed = 1;

    if (failed) {
	bu_vls_printf(gedp->ged_result_str, "%s: no resulting region, aborting\n", cmdname);
	if (tmp_tree)
	    db_free_tree(tmp_tree, &rt_uniresource);
	tmp_tree = (union tree *)NULL;
	nmg_km(bev_nmg_model);
	bev_nmg_model = (struct model *)NULL;
	return GED_ERROR;
    }
    /* New region remains part of this nmg "model" */
    NMG_CK_REGION(tmp_tree->tr_d.td_r);
    bu_vls_printf(gedp->ged_result_str, "%s: facetize %s\n", cmdname, tmp_tree->tr_d.td_name);

    nmg_vmodel(bev_nmg_model);

    /* Triangulate model, if requested */
    if (triangulate) {
	bu_vls_printf(gedp->ged_result_str, "%s: triangulating resulting object\n", cmdname);
	if (BU_SETJUMP) {
	    BU_UNSETJUMP;
	    bu_vls_printf(gedp->ged_result_str, "%s: WARNING: Triangulation failed!!!\n", cmdname);
	    if (tmp_tree)
		db_free_tree(tmp_tree, &rt_uniresource);
	    tmp_tree = (union tree *)NULL;
	    nmg_km(bev_nmg_model);
	    bev_nmg_model = (struct model *)NULL;
	    return GED_ERROR;
	}
	nmg_triangulate_model(bev_nmg_model, &gedp->ged_wdbp->wdb_tol);
	BU_UNSETJUMP;
    }

    bu_vls_printf(gedp->ged_result_str, "%s: converting NMG to database format\n", cmdname);

    /* Export NMG as a new solid */
    RT_DB_INTERNAL_INIT(&intern);
    intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
    intern.idb_type = ID_NMG;
    intern.idb_meth = &rt_functab[ID_NMG];
    intern.idb_ptr = (genptr_t)bev_nmg_model;
    bev_nmg_model = (struct model *)NULL;

    GED_DB_DIRADD(gedp, dp, newname, RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (genptr_t)&intern.idb_type, GED_ERROR);
    GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR);

    tmp_tree->tr_d.td_r = (struct nmgregion *)NULL;

    /* Free boolean tree, and the regions in it. */
    db_free_tree(tmp_tree, &rt_uniresource);

    return GED_OK;
}
Exemplo n.º 15
0
int
main(int argc, char *argv[])
{
    size_t i;
    int ret;
    int c;
    double percent;
    char copy_buffer[CP_BUF_SIZE] = {0};
    struct directory *dp;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    bu_log("%s", brlcad_ident("BRL-CAD to IGES Translator"));
    bu_log("Please direct bug reports to <*****@*****.**>\n\n");

    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.0005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    the_model = nmg_mm();
    BU_LIST_INIT(&RTG.rtg_vlfree);	/* for vlist macros */

    rt_init_resource(&rt_uniresource, 0, NULL);

    prog_name = argv[0];

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "ftsmd:a:n:o:p:r:vx:P:X:")) != -1) {
	switch (c) {
	    case 'f':		/* Select facetized output */
		mode = FACET_MODE;
		multi_file = 0;
		break;
	    case 't':
		mode = TRIMMED_SURF_MODE;
		multi_file = 0;
		break;
	    case 'm':		/* multi-file mode */
		multi_file = 1;
		mode = TRIMMED_SURF_MODE;
		break;
	    case 's':		/* Select NURB output */
		do_nurbs = 1;
		break;
	    case 'v':
		verbose++;
		break;
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		break;
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		break;
	    case 'd':		/* distance tolerance */
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		NMG_debug = RTG.NMG_debug;
		break;
	    case 'o':		/* Output file name. */
		output_file = bu_optarg;
		break;
	    case 'P':
		ncpu = atoi(bu_optarg);
		break;
	    default:
		usage(argv[0]);
		break;
	}
    }

    if (bu_optind+1 >= argc) {
	usage(argv[0]);
    }

    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    db_name = argv[0];
    if ((DBIP = db_open(db_name, DB_OPEN_READONLY)) == DBI_NULL) {
	perror("g-iges");
	bu_exit(1, "ERROR: unable to open geometry database file (%s)\n", db_name);
    }

    /* Scan the database */
    if (db_dirbuild(DBIP)) {
	bu_exit(1, "db_dirbuild failed\n");
    }

    if (!multi_file) {
	/* let the IGES routines know the selected tolerances and the database pointer */
	iges_init(&tol, &ttol, verbose, DBIP);

	/* Open the output file */
	if (output_file == NULL)
	    fp_dir = stdout;
	else {
	    if ((fp_dir = fopen(output_file, "wb")) == NULL) {
		perror(output_file);
		bu_exit(1, "Cannot open output file: %s\n", output_file);
	    }
	}

	/* Open the temporary file for the parameter section */
	if ((fp_param = bu_temp_file(NULL, 0)) == NULL) {
	    perror("g-iges");
	    bu_exit(1, "Cannot open temporary file\n");
	}

	/* Write start and global sections of the IGES file */
	w_start_global(fp_dir, fp_param, argv[0], prog_name, output_file, __DATE__, brlcad_version());
    } else {
	if (!bu_file_directory(output_file)) {
	    bu_exit(1, "-o option must provide a directory, %s is not a directory\n", output_file);
	}
    }

    /* Count object references */
/* for (i = 1; i < argc; i++) {
   dp = db_lookup(DBIP, argv[i], 1);
   db_functree(DBIP, dp, count_refs, 0, NULL);
   }	*/

    /* tree tops must have independent status, so we need to remember them */
    independent = (argv+1);
    no_of_indeps = (size_t)argc-1;

    if (mode == FACET_MODE) {
	/* Walk indicated tree(s).  Each region will be output
	 * as a single manifold solid BREP object */

	ret = db_walk_tree(DBIP, argc-1, (const char **)(argv+1),
			   ncpu,
			   &tree_state,
			   0,			/* take all regions */
			   do_nmg_region_end,
			   nmg_booltree_leaf_tess,
			   (void *)NULL);	/* in librt/nmg_bool.c */

	if (ret)
	    bu_exit(1, "g-iges: Could not facetize anything!");

	if (!multi_file) {
	    /* Now walk the same trees again, but only output groups */
	    for (i = 1; i < (size_t)argc; i++) {
		char *ptr;

		ptr = strrchr(argv[i], '/');
		if (ptr != NULL) {
		    ptr++;
		} else {
		    ptr = argv[i];
		}
		dp = db_lookup(DBIP, ptr, 1);
		if (!dp) {
		    bu_log("WARNING: Unable to locate %s in %s\n, skipping\n", ptr, db_name);
		    continue;
		}
		db_functree(DBIP, dp, csg_comb_func, 0, &rt_uniresource, NULL);
	    }
	}
    } else if (mode == CSG_MODE) {
	/* Walk indicated tree(s). Each combination and solid will be output
	 * as a CSG object, unless there is no IGES equivalent (then the
	 * solid will be tessellated and output as a BREP object) */

	for (i = 1; i < (size_t)argc; i++) {
	    dp = db_lookup(DBIP, argv[i], 1);
	    if (!dp) {
		bu_log("WARNING: Unable to locate %s in %s\n, skipping\n", argv[i], db_name);
		continue;
	    }
	    db_functree(DBIP, dp, csg_comb_func, csg_leaf_func, &rt_uniresource, NULL);
	}
    } else if (mode == TRIMMED_SURF_MODE) {
	/* Walk the indicated tree(s). Each region is output as a collection
	 * of trimmed NURBS */

	ret = db_walk_tree(DBIP, argc-1, (const char **)(argv+1),
			   ncpu,
			   &tree_state,
			   0,			/* take all regions */
			   do_nmg_region_end,
			   nmg_booltree_leaf_tess,
			   (void *)NULL);	/* in librt/nmg_bool.c */

	if (ret)
	    bu_exit(1, "g-iges: Could not facetize anything!");

    }

    if (!multi_file) {
	/* Copy the parameter section from the temporary file to the output file */
	if ((bu_fseek(fp_param, 0, 0))) {
	    perror("g-iges");
	    bu_exit(1, "Cannot seek to start of temporary file\n");
	}

	while ((i = fread(copy_buffer, 1, CP_BUF_SIZE, fp_param)))
	    if (fwrite(copy_buffer, 1, i, fp_dir) != i) {
		perror("g-iges");
		bu_exit(1, "Error in copying parameter data to %s\n", output_file);
	    }

	/* Write the terminate section */
	w_terminate(fp_dir);
    }

    /* Print some statistics */
    Print_stats(stdout);

    /* report on the success rate for facetizing regions */
    if (mode == FACET_MODE || mode == TRIMMED_SURF_MODE) {
	percent = 0;
	if (regions_tried>0) percent = ((double)regions_done * 100) / regions_tried;
	bu_log("Tried %d regions, %d converted to nmg's successfully.  %g%%\n",
	       regions_tried, regions_done, percent);
    }

    /* re-iterate warnings */
    if (scale_error || solid_error || comb_error)
	bu_log("WARNING: the IGES file produced has errors:\n");
    if (scale_error)
	bu_log("\t%d scaled objects found, written to IGES file without being scaled\n", scale_error);
    if (solid_error)
	bu_log("\t%d solids were not converted to IGES format\n", solid_error);
    if (comb_error)
	bu_log("\t%d combinations were not converted to IGES format\n", comb_error);

    return 0;
}
Exemplo n.º 16
0
int
main(int argc, char **argv)
{
    int	c;
    double percent;

    bu_setprogname(argv[0]);
    bu_setlinebuf(stderr);

    tree_state = rt_initial_tree_state;	/* struct copy */
    tree_state.ts_tol = &tol;
    tree_state.ts_ttol = &ttol;
    tree_state.ts_m = &the_model;

    /* Set up tessellation tolerance defaults */
    ttol.magic = RT_TESS_TOL_MAGIC;
    /* Defaults, updated by command line options. */
    ttol.abs = 0.0;
    ttol.rel = 0.01;
    ttol.norm = 0.0;

    /* Set up calculation tolerance defaults */
    /* FIXME: These need to be improved */
    tol.magic = BN_TOL_MAGIC;
    tol.dist = 0.0005;
    tol.dist_sq = tol.dist * tol.dist;
    tol.perp = 1e-6;
    tol.para = 1 - tol.perp;

    /* init resources we might need */
    rt_init_resource(&rt_uniresource, 0, NULL);

    /* make empty NMG model */
    the_model = nmg_mm();

    /* Get command line arguments. */
    while ((c = bu_getopt(argc, argv, "r:a:n:o:vx:D:X:h?")) != -1) {
	switch (c) {
	    case 'r':		/* Relative tolerance. */
		ttol.rel = atof(bu_optarg);
		break;
	    case 'a':		/* Absolute tolerance. */
		ttol.abs = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'n':		/* Surface normal tolerance. */
		ttol.norm = atof(bu_optarg);
		ttol.rel = 0.0;
		break;
	    case 'o':		/* Output file name. */
		/* grab output file name */
		break;
	    case 'v':
		verbose++;
		break;
	    case 'x':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.debug);
		break;
	    case 'D':
		tol.dist = atof(bu_optarg);
		tol.dist_sq = tol.dist * tol.dist;
		rt_pr_tol(&tol);
		break;
	    case 'X':
		sscanf(bu_optarg, "%x", (unsigned int *)&RTG.NMG_debug);
		NMG_debug = RTG.NMG_debug;
		break;
	    default:
		bu_exit(1, usage, argv[0]);
	}
    }

    if (bu_optind+1 >= argc)
	bu_exit(1, usage, argv[0]);

    /* Open output file */


    /* Open BRL-CAD database */
    argc -= bu_optind;
    argv += bu_optind;
    if ((dbip = db_open(argv[0], DB_OPEN_READONLY)) == DBI_NULL) {
	perror(argv[0]);
	bu_exit(1, "ERROR: Unable to open geometry database file (%s)\n", argv[0]);
    }
    if (db_dirbuild(dbip))
	bu_exit(1, "db_dirbuild failed\n");

    BN_CK_TOL(tree_state.ts_tol);
    RT_CK_TESS_TOL(tree_state.ts_ttol);

    if (verbose) {
	int i;

	bu_log("Model: %s\n", argv[0]);
	bu_log("Objects:");
	for (i = 1; i < argc; i++)
	    bu_log(" %s", argv[i]);
	bu_log("\nTessellation tolerances:\n\tabs = %g mm\n\trel = %g\n\tnorm = %g\n",
		tree_state.ts_ttol->abs, tree_state.ts_ttol->rel, tree_state.ts_ttol->norm);
	bu_log("Calculational tolerances:\n\tdist = %g mm perp = %g\n",
		tree_state.ts_tol->dist, tree_state.ts_tol->perp);
    }

    /* Walk indicated tree(s).  Each region will be output separately */
    (void) db_walk_tree(dbip, argc-1, (const char **)(argv+1),
			1,			/* ncpu */
			&tree_state,
			0,			/* take all regions */
			do_region_end,
			nmg_booltree_leaf_tess,
			(void *)NULL);	/* in librt/nmg_bool.c */

    percent = 0;
    if (regions_tried>0) {
	percent = ((double)regions_converted * 100) / regions_tried;
	bu_log("Tried %d regions, %d converted to NMG's successfully.  %g%%\n",
	       regions_tried, regions_converted, percent);
    }
    percent = 0;

    if (regions_tried > 0) {
	percent = ((double)regions_written * 100) / regions_tried;
	bu_log("                  %d triangulated successfully. %g%%\n",
		regions_written, percent);
    }

    bu_log("%zd triangles written\n", tot_polygons);

    bu_log("Tessellation parameters used:\n");
    bu_log("  abs  [-a]    %g\n", ttol.abs);
    bu_log("  rel  [-r]    %g\n", ttol.rel);
    bu_log("  norm [-n]    %g\n", ttol.norm);
    bu_log("  dist [-D]    %g\n", tol.dist);

    /* Release dynamic storage */
    nmg_km(the_model);
    rt_vlist_cleanup();
    db_close(dbip);

    return 0;
}
Exemplo n.º 17
0
/**
 * R T _ G E T T R E E S _ M U V E S
 *
 * User-called function to add a set of tree hierarchies to the active
 * set. Includes getting the indicated list of attributes and a
 * Tcl_HashTable for use with the ORCA man regions. (stashed in the
 * rt_i structure).
 *
 * This function may run in parallel, but is not multiply re-entrant
 * itself, because db_walk_tree() isn't multiply re-entrant.
 *
 * Semaphores used for critical sections in parallel mode:
 *	RT_SEM_TREE*	protects rti_solidheads[] lists, d_uses(solids)
 *	RT_SEM_RESULTS	protects HeadRegion, mdl_min/max, d_uses(reg), nregions
 *	RT_SEM_WORKER	(db_walk_dispatcher, from db_walk_tree)
 *	RT_SEM_STATS	nsolids
 *
 * INPUTS
 *	rtip	- RT instance pointer
 *	attrs	- array of pointers (NULL terminated) to strings (attribute names). A corresponding
 *		  array of "bu_mro" objects containing the attribute values will be attached to region
 *		  structures ("attr_values")
 *	argc	- number of trees to get
 *	argv	- array of char pointers to the names of the tree tops
 *	ncpus	- number of cpus to use
 *
 * Returns -
 *  	0	Ordinarily
 *	-1	On major error
 */
int
rt_gettrees_muves(struct rt_i *rtip, const char **attrs, int argc, const char **argv, int ncpus)
{
    register struct soltab	*stp;
    register struct region	*regp;
    Tcl_HashTable		*tbl;
    int			prev_sol_count;
    int			i;
    int			num_attrs=0;
    point_t			region_min, region_max;

    RT_CHECK_RTI(rtip);
    RT_CK_DBI(rtip->rti_dbip);

    if (!rtip->needprep)  {
	bu_log("ERROR: rt_gettree() called again after rt_prep!\n");
	return(-1);		/* FAIL */
    }

    if ( argc <= 0 )  return(-1);	/* FAIL */

    tbl = (Tcl_HashTable *)bu_malloc( sizeof( Tcl_HashTable ), "rtip->Orca_hash_tbl" );
    Tcl_InitHashTable( tbl, TCL_ONE_WORD_KEYS );
    rtip->Orca_hash_tbl = (genptr_t)tbl;

    prev_sol_count = rtip->nsolids;

    {
	struct db_tree_state	tree_state;

	tree_state = rt_initial_tree_state;	/* struct copy */
	tree_state.ts_dbip = rtip->rti_dbip;
	tree_state.ts_rtip = rtip;
	tree_state.ts_resp = NULL;	/* sanity.  Needs to be updated */

	if ( attrs ) {
	    if ( rtip->rti_dbip->dbi_version < 5 ) {
		bu_log( "WARNING: requesting attributes from an old database version (ignored)\n" );
		bu_avs_init_empty( &tree_state.ts_attrs );
	    } else {
		while ( attrs[num_attrs] ) {
		    num_attrs++;
		}
		if ( num_attrs ) {
		    bu_avs_init( &tree_state.ts_attrs,
				 num_attrs,
				 "avs in tree_state" );
		    num_attrs = 0;
		    while ( attrs[num_attrs] ) {
			bu_avs_add( &tree_state.ts_attrs,
				    attrs[num_attrs],
				    NULL );
			num_attrs++;
		    }
		} else {
		    bu_avs_init_empty( &tree_state.ts_attrs );
		}
	    }
	} else {
	    bu_avs_init_empty( &tree_state.ts_attrs );
	}

	/* ifdef this out for now, it is only using memory.  perhaps a
	 * better way of initiating ORCA stuff can be found.
	 */
#if 0
	bu_avs_add( &tree_state.ts_attrs, "ORCA_Comp", (char *)NULL );
#endif
	i = db_walk_tree( rtip->rti_dbip, argc, argv, ncpus,
			  &tree_state,
			  rt_gettree_region_start,
			  rt_gettree_region_end,
			  rt_gettree_leaf, (genptr_t)tbl );
	bu_avs_free( &tree_state.ts_attrs );
    }

    /* DEBUG:  Ensure that all region trees are valid */
    for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) )  {
	RT_CK_REGION(regp);
	db_ck_tree(regp->reg_treetop);
    }

    /*
     * Eliminate any "dead" solids that parallel code couldn't change.
     * First remove any references from the region tree, then remove
     * actual soltab structs from the soltab list.
     */
    for ( BU_LIST_FOR( regp, region, &(rtip->HeadRegion) ) )  {
	RT_CK_REGION(regp);
	rt_tree_kill_dead_solid_refs( regp->reg_treetop );
	(void)rt_tree_elim_nops( regp->reg_treetop, &rt_uniresource );
    }
 again:
    RT_VISIT_ALL_SOLTABS_START( stp, rtip )  {
	RT_CK_SOLTAB(stp);
	if ( stp->st_aradius <= 0 )  {
	    bu_log("rt_gettrees() cleaning up dead solid '%s'\n",
		   stp->st_dp->d_namep );
	    rt_free_soltab(stp);
	    /* Can't do rtip->nsolids--, that doubles as max bit number! */
	    /* The macro makes it hard to regain place, punt */
	    goto again;
	}
    } RT_VISIT_ALL_SOLTABS_END