/** * 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; }