예제 #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;
}
/**
 * prep and build bounding volumes... unfortunately, generating the
 * bounding sphere is too 'loose' (I think) and O(n^2).
 */
int
rt_metaball_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_metaball_internal *mb, *nmb;
    struct wdb_metaballpt *mbpt, *nmbpt;
    fastf_t minfstr = +INFINITY;

    if (rtip) RT_CK_RTI(rtip);

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

    /* generate a copy of the metaball */
    BU_ALLOC(nmb, struct rt_metaball_internal);
    nmb->magic = RT_METABALL_INTERNAL_MAGIC;
    BU_LIST_INIT(&nmb->metaball_ctrl_head);
    nmb->threshold = mb->threshold;
    nmb->method = mb->method;

    /* and copy the list of control points */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) {
	BU_ALLOC(nmbpt, struct wdb_metaballpt);
	nmbpt->fldstr = mbpt->fldstr;
	if (mbpt->fldstr < minfstr)
	    minfstr = mbpt->fldstr;
	nmbpt->sweat = mbpt->sweat;
	VMOVE(nmbpt->coord, mbpt->coord);
	BU_LIST_INSERT(&nmb->metaball_ctrl_head, &nmbpt->l);
    }

    /* find the bounding sphere */
    stp->st_aradius = rt_metaball_get_bounding_sphere(&stp->st_center, mb->threshold, mb);
    stp->st_bradius = stp->st_aradius * 1.01;

    /* XXX magic numbers, increase if scalloping is observed. :(*/
    nmb->initstep = minfstr / 2.0;
    if (nmb->initstep < (stp->st_aradius / 200.0))
	nmb->initstep = (stp->st_aradius / 200.0);
    else if (nmb->initstep > (stp->st_aradius / 10.0))
	nmb->initstep = (stp->st_aradius / 10.0);
    nmb->finalstep = /*stp->st_aradius * */minfstr / 1e5;

    /* generate a bounding box around the sphere...
     * XXX this can be optimized greatly to reduce the BSP presence... */
    if (rt_metaball_bbox(ip, &(stp->st_min), &(stp->st_max), &rtip->rti_tol)) return 1;
    stp->st_specific = (void *)nmb;
    return 0;
}
/* main point evaluation function, to be exposed to the ugly outside
 * world.
 */
fastf_t
rt_metaball_point_value(const point_t *p, const struct rt_metaball_internal *mb)
{
    RT_METABALL_CK_MAGIC(mb);
    switch (mb->method) {
	case METABALL_METABALL:
	    return rt_metaball_point_value_metaball(p, &mb->metaball_ctrl_head);
	case METABALL_ISOPOTENTIAL:
	    return rt_metaball_point_value_iso(p, &mb->metaball_ctrl_head);
	case METABALL_BLOB:
	    return rt_metaball_point_value_blob(p, &mb->metaball_ctrl_head);
	default:
	    break;
    }
    return 0;
}
void
rt_metaball_print(register const struct soltab *stp)
{
    int metaball_count = 0;
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;

    mb = (struct rt_metaball_internal *)stp->st_specific;
    RT_METABALL_CK_MAGIC(mb);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) ++metaball_count;
    bu_log("Metaball with %d points and a threshold of %g (%s rendering)\n", metaball_count, mb->threshold, rt_metaball_lookup_type_name(mb->method));
    metaball_count = 0;
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	bu_log("\t%d: %g field strength at (%g, %g, %g) and 'goo' of %g\n", ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord), mbpt->sweat);
    return;
}
/**
 * Calculate a bounding RPP around a metaball
 */
int
rt_metaball_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol))
{
    struct rt_metaball_internal *mb;
    point_t center;
    fastf_t radius;
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    VSETALL(center, 0);

    radius = rt_metaball_get_bounding_sphere(&center, mb->threshold, mb);

    VSET((*min), center[X] - radius, center[Y] - radius, center[Z] - radius);
    VSET((*max), center[X] + radius, center[Y] + radius, center[Z] + radius);
    return 0;
}
예제 #7
0
파일: metaball.c 프로젝트: cogitokat/brlcad
/**
 * R T _ M E T A B A L L _ G E T
 *
 * db get/g2asc
 */
int
rt_metaball_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *UNUSED(attr))
{
    struct rt_metaball_internal *mb = (struct rt_metaball_internal *)intern->idb_ptr;
    struct wdb_metaballpt *mbpt = NULL;

    RT_METABALL_CK_MAGIC(mb);

    /* write crap in */
    bu_vls_printf(logstr, "metaball %d %.25G {", mb->method, mb->threshold);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	    bu_vls_printf(logstr, "{%.25G %.25G %.25G %.25G %.25G}",
			    V3ARGS(mbpt->coord), mbpt->fldstr, mbpt->sweat);
    bu_vls_printf(logstr, "}");

    return 0;
}
/**
 * Free the storage associated with the rt_db_internal version of this
 * solid.  This only effects the in-memory copy.
 */
void
rt_metaball_ifree(struct rt_db_internal *ip)
{
    register struct rt_metaball_internal *metaball;
    register struct wdb_metaballpt *mbpt;

    RT_CK_DB_INTERNAL(ip);

    metaball = (struct rt_metaball_internal*)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(metaball);

    if (metaball->metaball_ctrl_head.magic != 0)
	while (BU_LIST_WHILE(mbpt, wdb_metaballpt, &metaball->metaball_ctrl_head)) {
	    BU_LIST_DEQUEUE(&(mbpt->l));
	    BU_PUT(mbpt, struct wdb_metaballpt);
	}
    bu_free(ip->idb_ptr, "metaball ifree");
    ip->idb_ptr = ((void *)0);
}
/**
 * storage is something like
 * long numpoints
 * long method
 * fastf_t threshold
 * fastf_t X1 (start point)
 * fastf_t Y1
 * fastf_t Z1
 * fastf_t fldstr1
 * fastf_t sweat1 (end point)
 * fastf_t X2 (start point)
 * ...
 */
int
rt_metaball_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
{
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;
    int metaball_count = 0, i = 1;
    /* must be double for import and export */
    double *buf = NULL;

    if (dbip) RT_CK_DBI(dbip);

    RT_CK_DB_INTERNAL(ip);
    if (ip->idb_type != ID_METABALL)
	return -1;
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    if (mb->metaball_ctrl_head.magic == 0) return -1;

    /* Count number of points */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) metaball_count++;

    BU_CK_EXTERNAL(ep);
    ep->ext_nbytes = SIZEOF_NETWORK_DOUBLE*(1+5*metaball_count) + 2*SIZEOF_NETWORK_LONG;
    ep->ext_buf = (uint8_t *)bu_malloc(ep->ext_nbytes, "metaball external");
    if (ep->ext_buf == NULL)
	bu_bomb("Failed to allocate DB space!\n");
    *(uint32_t *)ep->ext_buf = htonl(metaball_count);
    *(uint32_t *)(ep->ext_buf + SIZEOF_NETWORK_LONG) = htonl(mb->method);

    /* pack the point data */
    buf = (double *)bu_malloc((metaball_count*5+1)*SIZEOF_NETWORK_DOUBLE, "rt_metaball_export5: buf");
    buf[0] = mb->threshold;
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head), i+=5) {
	VSCALE(&buf[i], mbpt->coord, local2mm);
	buf[i+3] = mbpt->fldstr * local2mm;
	buf[i+4] = mbpt->sweat;
    }
    bu_cv_htond((unsigned char *)ep->ext_buf + 2*SIZEOF_NETWORK_LONG, (unsigned char *)buf, 1 + 5 * metaball_count);
    bu_free(buf, "rt_metaball_export5: buf");
    return 0;
}
/**
 * Make human-readable formatted presentation of this solid. First
 * line describes type of solid. Additional lines are indented one
 * tab, and give parameter values.
 */
int
rt_metaball_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double UNUSED(mm2local))
{
    int metaball_count = 0;
    char buf[BUFSIZ];
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;

    RT_CK_DB_INTERNAL(ip);
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) metaball_count++;

    snprintf(buf, BUFSIZ, "Metaball with %d points and a threshold of %g (%s rendering)\n", metaball_count, mb->threshold, rt_metaball_lookup_type_name(mb->method));
    bu_vls_strcat(str, buf);

    if (!verbose)
	return 0;

    metaball_count = 0;
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head)) {
	switch (mb->method) {
	    case METABALL_ISOPOTENTIAL:
		snprintf(buf, BUFSIZ, "\t%d: %g field strength at (%g, %g, %g)\n",
			 ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord));
		break;
	    case METABALL_METABALL:
	    case METABALL_BLOB:
		snprintf(buf, BUFSIZ, "\t%d: %g field strength at (%g, %g, %g) and blobbiness factor of %g\n",
			 ++metaball_count, mbpt->fldstr, V3ARGS(mbpt->coord), mbpt->sweat);
		break;
	    default:
		bu_bomb("Bad metaball method");	/* asplode */
	}
	bu_vls_strcat(str, buf);
    }
    return 0;
}
int
rt_metaball_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_metaball_internal *mb;
    struct wdb_metaballpt *mbpt;
    point_t bsc;
    fastf_t rad;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    mb = (struct rt_metaball_internal *)ip->idb_ptr;
    RT_METABALL_CK_MAGIC(mb);
    rad = rt_metaball_get_bounding_sphere(&bsc, mb->threshold, mb);
    /* cope with the case where 0 points are defined. */
    if (rad<0)
	return 0;
#if PLOT_THE_BIG_BOUNDING_SPHERE
    rt_metaball_plot_sph(vhead, &bsc, rad);
#endif
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	rt_metaball_plot_sph(vhead, &mbpt->coord, mbpt->fldstr / mb->threshold);
    return 0;
}
예제 #12
0
/*
 * Default keypoint in model space is established in "pt". Returns
 * GED_ERROR if unable to determine a keypoint, otherwise returns
 * GED_OK.
 */
int
_ged_get_solid_keypoint(struct ged *const gedp,
			fastf_t *const pt,
			const struct rt_db_internal *const ip,
			const fastf_t *const mat)
{
    point_t mpt;

    RT_CK_DB_INTERNAL(ip);

    switch (ip->idb_type) {
	case ID_CLINE:
	    {
		struct rt_cline_internal *cli =
		    (struct rt_cline_internal *)ip->idb_ptr;

		RT_CLINE_CK_MAGIC(cli);

		VMOVE(mpt, cli->v);
		break;
	    }
	case ID_PARTICLE:
	    {
		struct rt_part_internal *part =
		    (struct rt_part_internal *)ip->idb_ptr;

		RT_PART_CK_MAGIC(part);

		VMOVE(mpt, part->part_V);
		break;
	    }
	case ID_PIPE:
	    {
		struct rt_pipe_internal *pipeip;
		struct wdb_pipept *pipe_seg;

		pipeip = (struct rt_pipe_internal *)ip->idb_ptr;

		RT_PIPE_CK_MAGIC(pipeip);

		pipe_seg = BU_LIST_FIRST(wdb_pipept, &pipeip->pipe_segs_head);
		VMOVE(mpt, pipe_seg->pp_coord);
		break;
	    }
	case ID_METABALL:
	    {
		struct rt_metaball_internal *metaball =
		    (struct rt_metaball_internal *)ip->idb_ptr;
		struct wdb_metaballpt *metaballpt;

		RT_METABALL_CK_MAGIC(metaball);

		VSETALL(mpt, 0.0);
		metaballpt = BU_LIST_FIRST(wdb_metaballpt,
					   &metaball->metaball_ctrl_head);
		VMOVE(mpt, metaballpt->coord);
		break;
	    }
	case ID_ARBN:
	    {
		struct rt_arbn_internal *arbn =
		    (struct rt_arbn_internal *)ip->idb_ptr;
		size_t i, j, k;
		int good_vert = 0;

		RT_ARBN_CK_MAGIC(arbn);
		for (i = 0; i < arbn->neqn; i++) {
		    for (j = i + 1; j < arbn->neqn; j++) {
			for (k = j + 1; k < arbn->neqn; k++) {
			    if (!bn_mkpoint_3planes(mpt, arbn->eqn[i],
						    arbn->eqn[j],
						    arbn->eqn[k])) {
				size_t l;

				good_vert = 1;
				for (l = 0; l < arbn->neqn; l++) {
				    if (l == i || l == j || l == k)
					continue;

				    if (DIST_PT_PLANE(mpt,
					arbn->eqn[l]) >
					gedp->ged_wdbp->wdb_tol.dist) {
					good_vert = 0;
					break;
				    }
				}

				if (good_vert)
				    break;
			    }
			}
			if (good_vert)
			    break;
		    }
		    if (good_vert)
			break;
		}

		break;
	    }
	case ID_EBM:
	    {
		struct rt_ebm_internal *ebm =
		    (struct rt_ebm_internal *)ip->idb_ptr;
		point_t pnt;

		RT_EBM_CK_MAGIC(ebm);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, ebm->mat, pnt);
		break;
	    }
	case ID_BOT:
	    {
		struct rt_bot_internal *bot =
		    (struct rt_bot_internal *)ip->idb_ptr;

		    VMOVE(mpt, bot->vertices);
		break;
	    }
	case ID_DSP:
	    {
		struct rt_dsp_internal *dsp =
		    (struct rt_dsp_internal *)ip->idb_ptr;
		point_t pnt;

		RT_DSP_CK_MAGIC(dsp);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, dsp->dsp_stom, pnt);
		break;
	    }
	case ID_HF:
	    {
		struct rt_hf_internal *hf =
		    (struct rt_hf_internal *)ip->idb_ptr;

		RT_HF_CK_MAGIC(hf);

		VMOVE(mpt, hf->v);
		break;
	    }
	case ID_VOL:
	    {
		struct rt_vol_internal *vol =
		    (struct rt_vol_internal *)ip->idb_ptr;
		point_t pnt;

		RT_VOL_CK_MAGIC(vol);

		VSETALL(pnt, 0.0);
		MAT4X3PNT(mpt, vol->mat, pnt);
		break;
	    }
	case ID_HALF:
	    {
		struct rt_half_internal *haf =
		    (struct rt_half_internal *)ip->idb_ptr;
		RT_HALF_CK_MAGIC(haf);

		VSCALE(mpt, haf->eqn, haf->eqn[H]);
		break;
	    }
	case ID_ARB8:
	    {
		struct rt_arb_internal *arb =
		    (struct rt_arb_internal *)ip->idb_ptr;
		RT_ARB_CK_MAGIC(arb);

		VMOVE(mpt, arb->pt[0]);
		break;
	    }
	case ID_ELL:
	case ID_SPH:
	    {
		struct rt_ell_internal *ell =
		    (struct rt_ell_internal *)ip->idb_ptr;
		RT_ELL_CK_MAGIC(ell);

		VMOVE(mpt, ell->v);
		break;
	    }
	case ID_SUPERELL:
	    {
		struct rt_superell_internal *superell =
		    (struct rt_superell_internal *)ip->idb_ptr;
		RT_SUPERELL_CK_MAGIC(superell);

		VMOVE(mpt, superell->v);
		break;
	    }
	case ID_TOR:
	    {
		struct rt_tor_internal *tor =
		    (struct rt_tor_internal *)ip->idb_ptr;
		RT_TOR_CK_MAGIC(tor);

		VMOVE(mpt, tor->v);
		break;
	    }
	case ID_TGC:
	case ID_REC:
	    {
		struct rt_tgc_internal *tgc =
		    (struct rt_tgc_internal *)ip->idb_ptr;
		RT_TGC_CK_MAGIC(tgc);

		VMOVE(mpt, tgc->v);
		break;
	    }
	case ID_GRIP:
	    {
		struct rt_grip_internal *gip =
		    (struct rt_grip_internal *)ip->idb_ptr;
		RT_GRIP_CK_MAGIC(gip);
		VMOVE(mpt, gip->center);
		break;
	    }
	case ID_ARS:
	    {
		struct rt_ars_internal *ars =
		    (struct rt_ars_internal *)ip->idb_ptr;
		RT_ARS_CK_MAGIC(ars);

		VMOVE(mpt, &ars->curves[0][0]);
		break;
	    }
	case ID_RPC:
	    {
		struct rt_rpc_internal *rpc =
		    (struct rt_rpc_internal *)ip->idb_ptr;
		RT_RPC_CK_MAGIC(rpc);

		VMOVE(mpt, rpc->rpc_V);
		break;
	    }
	case ID_RHC:
	    {
		struct rt_rhc_internal *rhc =
		    (struct rt_rhc_internal *)ip->idb_ptr;
		RT_RHC_CK_MAGIC(rhc);

		VMOVE(mpt, rhc->rhc_V);
		break;
	    }
	case ID_EPA:
	    {
		struct rt_epa_internal *epa =
		    (struct rt_epa_internal *)ip->idb_ptr;
		RT_EPA_CK_MAGIC(epa);

		VMOVE(mpt, epa->epa_V);
		break;
	    }
	case ID_EHY:
	    {
		struct rt_ehy_internal *ehy =
		    (struct rt_ehy_internal *)ip->idb_ptr;
		RT_EHY_CK_MAGIC(ehy);

		VMOVE(mpt, ehy->ehy_V);
		break;
	    }
	case ID_HYP:
	    {
		struct rt_hyp_internal *hyp =
		    (struct rt_hyp_internal *)ip->idb_ptr;
		RT_HYP_CK_MAGIC(hyp);

		VMOVE(mpt, hyp->hyp_Vi);
		break;
	    }
	case ID_ETO:
	    {
		struct rt_eto_internal *eto =
		    (struct rt_eto_internal *)ip->idb_ptr;
		RT_ETO_CK_MAGIC(eto);

		VMOVE(mpt, eto->eto_V);
		break;
	    }
	case ID_POLY:
	    {
		struct rt_pg_face_internal *_poly;
		struct rt_pg_internal *pg =
		    (struct rt_pg_internal *)ip->idb_ptr;
		RT_PG_CK_MAGIC(pg);

		_poly = pg->poly;
		VMOVE(mpt, _poly->verts);
		break;
	    }
	case ID_SKETCH:
	    {
		struct rt_sketch_internal *skt =
		    (struct rt_sketch_internal *)ip->idb_ptr;
		RT_SKETCH_CK_MAGIC(skt);

		VMOVE(mpt, skt->V);
		break;
	    }
	case ID_EXTRUDE:
	    {
		struct rt_extrude_internal *extr =
		    (struct rt_extrude_internal *)ip->idb_ptr;
		RT_EXTRUDE_CK_MAGIC(extr);

		if (extr->skt && extr->skt->verts) {
		    VJOIN2(mpt, extr->V, extr->skt->verts[0][0], extr->u_vec,
			   extr->skt->verts[0][1], extr->v_vec);
		} else {
		    VMOVE(mpt, extr->V);
		}
		break;
	    }
	case ID_NMG:
	    {
		struct vertex *v;
		struct vertexuse *vu;
		struct edgeuse *eu;
		struct loopuse *lu;
		struct faceuse *fu;
		struct shell *s;
		struct nmgregion *r;
		struct model *m =
		    (struct model *) ip->idb_ptr;
		NMG_CK_MODEL(m);

		/* set default first */
		VSETALL(mpt, 0.0);

		if (BU_LIST_IS_EMPTY(&m->r_hd))
		    break;

		r = BU_LIST_FIRST(nmgregion, &m->r_hd);
		if (!r)
		    break;
		NMG_CK_REGION(r);

		if (BU_LIST_IS_EMPTY(&r->s_hd))
		    break;

		s = BU_LIST_FIRST(shell, &r->s_hd);
		if (!s)
		    break;
		NMG_CK_SHELL(s);

		if (BU_LIST_IS_EMPTY(&s->fu_hd))
		    fu = (struct faceuse *)NULL;
		else
		    fu = BU_LIST_FIRST(faceuse, &s->fu_hd);
		if (fu) {
		    NMG_CK_FACEUSE(fu);
		    lu = BU_LIST_FIRST(loopuse, &fu->lu_hd);
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->lu_hd))
		    lu = (struct loopuse *)NULL;
		else
		    lu = BU_LIST_FIRST(loopuse, &s->lu_hd);
		if (lu) {
		    NMG_CK_LOOPUSE(lu);
		    if (BU_LIST_FIRST_MAGIC(&lu->down_hd) == NMG_EDGEUSE_MAGIC) {
			eu = BU_LIST_FIRST(edgeuse, &lu->down_hd);
			NMG_CK_EDGEUSE(eu);
			NMG_CK_VERTEXUSE(eu->vu_p);
			v = eu->vu_p->v_p;
		    } else {
			vu = BU_LIST_FIRST(vertexuse, &lu->down_hd);
			NMG_CK_VERTEXUSE(vu);
			v = vu->v_p;
		    }
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		if (BU_LIST_IS_EMPTY(&s->eu_hd))
		    eu = (struct edgeuse *)NULL;
		else
		    eu = BU_LIST_FIRST(edgeuse, &s->eu_hd);
		if (eu) {
		    NMG_CK_EDGEUSE(eu);
		    NMG_CK_VERTEXUSE(eu->vu_p);
		    v = eu->vu_p->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
		vu = s->vu_p;
		if (vu) {
		    NMG_CK_VERTEXUSE(vu);
		    v = vu->v_p;
		    NMG_CK_VERTEX(v);
		    if (!v->vg_p)
			break;
		    VMOVE(mpt, v->vg_p->coord);
		    break;
		}
	    }
	default:
	    VSETALL(mpt, 0.0);
	    bu_vls_printf(gedp->ged_result_str,
			  "get_solid_keypoint: unrecognized solid type");
	    return GED_ERROR;
    }
    MAT4X3PNT(pt, mat, mpt);
    return GED_OK;
}
예제 #13
0
/**
 * R T _ M E T A B A L L _ T E S S
 *
 * Tessellate a metaball.
 */
int
rt_metaball_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
{
    struct rt_metaball_internal *mb;
    fastf_t mtol, radius;
    point_t center, min, max;
    fastf_t i, j, k, finalstep = +INFINITY;
    struct bu_vls times = BU_VLS_INIT_ZERO;
    struct wdb_metaballpt *mbpt;
    struct shell *s;
    int numtri = 0;

    if (r == NULL || m == NULL)
	return -1;
    *r = NULL;

    NMG_CK_MODEL(m);

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

    rt_prep_timer();

    /* since this geometry isn't necessarily prepped, we have to figure out the
     * finalstep and bounding box manually. */
    for (BU_LIST_FOR(mbpt, wdb_metaballpt, &mb->metaball_ctrl_head))
	V_MIN(finalstep, mbpt->fldstr);
    finalstep /= (fastf_t)1e5;

    radius = rt_metaball_get_bounding_sphere(&center, mb->threshold, mb);
    if(radius < 0) {	/* no control points */
	bu_log("Attempting to tesselate metaball with no control points");
	return -1;
    }
    rt_metaball_bbox(ip, &min, &max, tol);

    /* TODO: get better sampling tolerance, unless this is "good enough" */
    mtol = ttol->abs;
    V_MAX(mtol, ttol->rel * radius * 10);
    V_MAX(mtol, tol->dist);

    *r = nmg_mrsv(m);	/* new empty nmg */
    s = BU_LIST_FIRST(shell, &(*r)->s_hd);

    /* the incredibly naïve approach. Time could be cut in half by simply
     * caching 4 point values, more by actually marching or doing active
     * refinement. This is the simplest pattern for now.
     */
    for (i = min[X]; i < max[X]; i += mtol)
	for (j = min[Y]; j < max[Y]; j += mtol)
	    for (k = min[Z]; k < max[Z]; k += mtol) {
		point_t p[8];
		int pv = 0;

		/* generate the vertex values */
#define MEH(c,di,dj,dk) VSET(p[c], i+di, j+dj, k+dk); pv |= rt_metaball_point_inside((const point_t *)&p[c], mb) << c;
		MEH(0, 0, 0, mtol);
		MEH(1, mtol, 0, mtol);
		MEH(2, mtol, 0, 0);
		MEH(3, 0, 0, 0);
		MEH(4, 0, mtol, mtol);
		MEH(5, mtol, mtol, mtol);
		MEH(6, mtol, mtol, 0);
		MEH(7, 0, mtol, 0);
#undef MEH

		if ( pv != 0 && pv != 255 ) {	/* entire cube is either inside or outside */
		    point_t edges[12];
		    int rval;

		    /* compute the edge values (if needed) */
#define MEH(a,b,c) if(!(pv&(1<<b)&&pv&(1<<c))) { \
    rt_metaball_find_intersection(edges+a, mb, (const point_t *)(p+b), (const point_t *)(p+c), mtol, finalstep); \
}

		    /* magic numbers! an edge, then the two attached vertices.
		     * For edge/vertex mapping, refer to the awesome ascii art
		     * at the beginning of this file. */
		    MEH(0 ,0,1);
		    MEH(1 ,1,2);
		    MEH(2 ,2,3);
		    MEH(3 ,0,3);
		    MEH(4 ,4,5);
		    MEH(5 ,5,6);
		    MEH(6 ,6,7);
		    MEH(7 ,4,7);
		    MEH(8 ,0,4);
		    MEH(9 ,1,5);
		    MEH(10,2,6);
		    MEH(11,3,7);
#undef MEH

		    rval = nmg_mc_realize_cube(s, pv, (point_t *)edges, tol);
		    numtri += rval;
		    if(rval < 0) {
			bu_log("Error attempting to realize a cube O.o\n");
			return rval;
		    }
		}
	    }

    nmg_mark_edges_real(&s->l.magic);
    nmg_region_a(*r, tol);

    nmg_model_fuse(m, tol);

    rt_get_timer(&times, NULL);
    bu_log("metaball tesselate (%d triangles): %s\n", numtri, bu_vls_addr(&times));

    return 0;
}