示例#1
0
/**
 * Creates one metaball object that includes all points from an
 * existing list (in 'av') of named metaballs.  This routine creates
 * an rt_metaball_internal object directly via LIBRT given it requires
 * reading existing metaballs from the database.
 */
static void
mix_balls(struct db_i *dbip, const char *name, int ac, const char *av[])
{
    int i;
    struct directory *dp;
    struct rt_metaball_internal *newmp;

    RT_CK_DBI(dbip);

    /* allocate a struct rt_metaball_internal object that we'll
     * manually fill in with points from the other metaballs being
     * joined together.
     */
    BU_ALLOC(newmp, struct rt_metaball_internal);
    newmp->magic = RT_METABALL_INTERNAL_MAGIC;
    newmp->threshold = 1.0;
    newmp->method = 1;
    BU_LIST_INIT(&newmp->metaball_ctrl_head);

    bu_log("Combining together the following metaballs:\n");

    for (i = 0; i < ac; i++) {
	struct rt_db_internal dir;
	struct rt_metaball_internal *mp;
	struct wdb_metaballpt *mpt;

	/* get a handle on the existing database object */
	bu_log("\t%s\n", av[i]);
	dp = db_lookup(dbip, av[i], 1);
	if (!dp) {
	    bu_log("Unable to find %s\n", av[i]);
	    continue;
	}

	/* load the existing database object */
	if (rt_db_get_internal(&dir, dp, dbip, NULL, &rt_uniresource) < 0) {
	    bu_log("Unable to load %s\n", av[i]);
	    continue;
	}

	/* access the metaball-specific internal structure */
	mp = (struct rt_metaball_internal *)dir.idb_ptr;
	RT_METABALL_CK_MAGIC(mp);

	/* iterate over each point in that database object and add it
	 * to our new metaball.
	 */
	for (BU_LIST_FOR(mpt, wdb_metaballpt, &mp->metaball_ctrl_head)) {
	    bu_log("Adding point (%lf %lf %lf)\n", V3ARGS(mpt->coord));
	    rt_metaball_add_point(newmp, (const point_t *)&mpt->coord, mpt->fldstr, mpt->sweat);
	}
    }

    bu_log("Joining balls together and creating [%s] object\n", name);

    /* write out new "mega metaball" out to disk */
    dbip->dbi_wdbp = wdb_dbopen(dbip, RT_WDB_TYPE_DB_DISK);
    wdb_export(dbip->dbi_wdbp, name, newmp, ID_METABALL, 1.0);
}
/**
 * used for db put/asc2g
 */
int
rt_metaball_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
{
    struct rt_metaball_internal *mb;
    const char *pts;
    const char *pend;
    double thresh;

    if (argc != 3)  {
	bu_vls_printf(logstr, "Invalid number of arguments: %d\n", argc);
	return BRLCAD_ERROR;
    }

    RT_CK_DB_INTERNAL(intern);
    mb = (struct rt_metaball_internal *)intern->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);

    if ( strlen(*argv) != 1 || (**argv < '0' || **argv > '2') ) {
	bu_vls_printf(logstr, "Invalid method type, must be one of 0, 1, or 2.");
	return BRLCAD_ERROR;
    }
    mb->method = *argv[0] - '0';
    sscanf(argv[1], "%lG", &thresh);
    mb->threshold = thresh;
    BU_LIST_INIT(&mb->metaball_ctrl_head);

    pts = argv[2];
    pend = pts + strlen(pts);

    while (1) {
	int len;
	double xyz[3];
	double fldstr, goo;
	point_t loc;
	const point_t *locp = (const point_t *)&loc;

	while ( pts < pend && *pts != '{' ) ++pts;
	if (pts >= pend) break;
	len = sscanf(pts, "{%lG %lG %lG %lG %lG}", &xyz[0], &xyz[1], &xyz[2], &fldstr, &goo);
	VMOVE(loc, xyz);

	if (len == EOF) break;
	if (len != 5) {
	    bu_vls_printf(logstr, "Failed to parse point information: \"%s\"", pts);
	    return BRLCAD_ERROR;
	}
	pts++;
	if (rt_metaball_add_point (mb, locp, fldstr, goo)) {
	    bu_vls_printf(logstr, "Failure adding point: {%f %f %f %f %f}", V3ARGS(loc), fldstr, goo);
	    return BRLCAD_ERROR;
	}
    }

    return BRLCAD_OK;
}