Example #1
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_arbn_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
{
    struct rt_arbn_internal *aip =
	(struct rt_arbn_internal *)ip->idb_ptr;
    char buf[256];
    size_t i;

    RT_ARBN_CK_MAGIC(aip);
    sprintf(buf, "arbn bounded by %lu planes\n", (long unsigned)aip->neqn);
    bu_vls_strcat(str, buf);

    if (!verbose) return 0;

    for (i = 0; i < aip->neqn; i++) {
	sprintf(buf, "\t%lu: (%g, %g, %g) %g\n",
		(long unsigned)i,
		INTCLAMP(aip->eqn[i][X]),		/* should have unit length */
		INTCLAMP(aip->eqn[i][Y]),
		INTCLAMP(aip->eqn[i][Z]),
		INTCLAMP(aip->eqn[i][W] * mm2local));
	bu_vls_strcat(str, buf);
    }
    return 0;
}
Example #2
0
/**
 * Return the "curvature" of the ARB face.
 * Pick a principle direction orthogonal to normal, and
 * indicate no curvature.
 */
void
rt_arbn_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp)
{
    struct rt_arbn_internal *arbn = (struct rt_arbn_internal *)stp->st_specific;

    RT_ARBN_CK_MAGIC(arbn);

    bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal);
    cvp->crv_c1 = cvp->crv_c2 = 0;
}
Example #3
0
int
rt_arbn_params(struct pc_pc_set *UNUSED(ps), const struct rt_db_internal *ip)
{
    struct rt_arbn_internal *aip;

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    return 0;			/* OK */
}
Example #4
0
int
rt_arbn_export4(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
{
    struct rt_arbn_internal *aip;
    union record *rec;
    size_t ngrans;
    size_t i;

    /* scaling buffer must be double, not fastf_t */
    double *sbuf;
    double *sp;

    if (dbip) RT_CK_DBI(dbip);

    RT_CK_DB_INTERNAL(ip);
    if (ip->idb_type != ID_ARBN) return -1;
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    if (aip->neqn <= 0) return -1;

    /*
     * The network format for a double is 8 bytes and there are 4
     * doubles per plane equation.
     */
    ngrans = (aip->neqn * 8 * ELEMENTS_PER_PLANE + sizeof(union record)-1) /
	sizeof(union record);

    BU_CK_EXTERNAL(ep);
    ep->ext_nbytes = (ngrans + 1) * sizeof(union record);
    ep->ext_buf = (uint8_t *)bu_calloc(1, ep->ext_nbytes, "arbn external");
    rec = (union record *)ep->ext_buf;

    rec[0].n.n_id = DBID_ARBN;
    *(uint32_t *)rec[0].n.n_neqn = htonl(aip->neqn);
    *(uint32_t *)rec[0].n.n_grans = htonl(ngrans);

    /* Take the data from the caller, and scale it, into sbuf */
    sp = sbuf = (double *)bu_malloc(
	aip->neqn * sizeof(double) * ELEMENTS_PER_PLANE, "arbn temp");
    for (i = 0; i < aip->neqn; i++) {
	/* Normal is unscaled, should have unit length; d is scaled */
	*sp++ = aip->eqn[i][X];
	*sp++ = aip->eqn[i][Y];
	*sp++ = aip->eqn[i][Z];
	*sp++ = aip->eqn[i][W] * local2mm;
    }

    bu_cv_htond((unsigned char *)&rec[1], (unsigned char *)sbuf, aip->neqn * ELEMENTS_PER_PLANE);

    bu_free((char *)sbuf, "arbn temp");
    return 0;			/* OK */
}
Example #5
0
/**
 * For a hit on a face of an ARB, return the (u, v) coordinates
 * of the hit point.  0 <= u, v <= 1.
 * u extends along the arb_U direction defined by B-A,
 * v extends along the arb_V direction defined by Nx(B-A).
 */
void
rt_arbn_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp)
{
    struct rt_arbn_internal *arbn = (struct rt_arbn_internal *)stp->st_specific;

    if (ap) RT_CK_APPLICATION(ap);
    RT_ARBN_CK_MAGIC(arbn);
    if (hitp) RT_CK_HIT(hitp);

    if (uvp) {
	uvp->uv_u = uvp->uv_v = 0;
	uvp->uv_du = uvp->uv_dv = 0;
    }
}
Example #6
0
/**
 * Free the storage associated with the rt_db_internal version of this solid.
 */
void
rt_arbn_ifree(struct rt_db_internal *ip)
{
    struct rt_arbn_internal *aip;

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    if (aip->neqn > 0)
	bu_free((char *)aip->eqn, "rt_arbn_internal eqn[]");
    bu_free((char *)aip, "rt_arbn_internal");

    ip->idb_ptr = (void *)0;	/* sanity */
}
Example #7
0
/**
 * Calculate a bounding RPP for an ARBN
 */
int
rt_arbn_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
    size_t i, j, k;
    struct rt_arbn_internal *aip;
    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    VSETALL((*min), INFINITY);
    VSETALL((*max), -INFINITY);

    /* Discover all vertices, use to calculate RPP */
    for (i = 0; i < aip->neqn-2; i++) {
	for (j = i+1; j < aip->neqn-1; j++) {
	    double dot;

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (((dot) <= -SMALL_FASTF) ? (NEAR_EQUAL((dot), -1.0,  RT_DOT_TOL)) : (NEAR_EQUAL((dot), 1.0, RT_DOT_TOL))) continue;

	    /* Have an edge line, isect with higher numbered planes */
	    for (k = j + 1; k < aip->neqn; k++) {
		size_t m;
		size_t next_k;
		point_t pt;

		next_k = 0;

		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m)
			continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > RT_LEN_TOL) {
			next_k = 1;
			break;
		    }
		}
		if (next_k != 0) continue;

		VMINMAX((*min), (*max), pt);
	    }
	}
    }

    return 0;
}
Example #8
0
int
rt_arbn_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
{
    struct rt_arbn_internal *aip;
    size_t i;
    int double_count;
    int byte_count;

    /* must be double for export */
    double *vec;
    double *sp;

    RT_CK_DB_INTERNAL(ip);
    if (dbip) RT_CK_DBI(dbip);

    if (ip->idb_type != ID_ARBN) return -1;
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    if (aip->neqn <= 0) return -1;

    double_count = aip->neqn * ELEMENTS_PER_PLANE;
    byte_count = double_count * SIZEOF_NETWORK_DOUBLE;

    BU_CK_EXTERNAL(ep);
    ep->ext_nbytes = SIZEOF_NETWORK_LONG + byte_count;
    ep->ext_buf = (uint8_t *)bu_malloc(ep->ext_nbytes, "arbn external");

    *(uint32_t *)ep->ext_buf = htonl(aip->neqn);

    /* Take the data from the caller, and scale it, into vec */
    sp = vec = (double *)bu_malloc(byte_count, "arbn temp");
    for (i = 0; i < aip->neqn; i++) {
	/* Normal is unscaled, should have unit length; d is scaled */
	*sp++ = aip->eqn[i][X];
	*sp++ = aip->eqn[i][Y];
	*sp++ = aip->eqn[i][Z];
	*sp++ = aip->eqn[i][W] * local2mm;
    }

    /* Convert from internal (host) to database (network) format */
    bu_cv_htond((unsigned char *)ep->ext_buf + SIZEOF_NETWORK_LONG, (unsigned char *)vec, double_count);

    bu_free((char *)vec, "arbn temp");
    return 0;			/* OK */
}
Example #9
0
void
rt_arbn_print(const struct soltab *stp)
{
    size_t i;
    struct rt_arbn_internal *arbp = (struct rt_arbn_internal *)stp->st_specific;

    RT_ARBN_CK_MAGIC(arbp);
    bu_log("arbn bounded by %zu planes\n", arbp->neqn);

    for (i = 0; i < arbp->neqn; i++) {
	bu_log("\t%zu: (%g, %g, %g) %g\n",
	       i,
	       INTCLAMP(arbp->eqn[i][X]),		/* should have unit length */
	       INTCLAMP(arbp->eqn[i][Y]),
	       INTCLAMP(arbp->eqn[i][Z]),
	       INTCLAMP(arbp->eqn[i][W]));
    }
}
Example #10
0
/**
 * Routine to format the parameters of an ARBN primitive for "db get"
 *
 * Legal requested parameters include:
 *	"N" - number of equations
 *	"P" - list of all the planes
 *	"P#" - the specified plane number (0 based)
 *	no arguments returns everything
 */
int
rt_arbn_get(struct bu_vls *logstr, const struct rt_db_internal *intern, const char *attr)
{
    struct rt_arbn_internal *arbn=(struct rt_arbn_internal *)intern->idb_ptr;
    size_t i;
    long val;

    RT_ARBN_CK_MAGIC(arbn);

    if (attr == (char *)NULL) {
	bu_vls_strcpy(logstr, "arbn");
	bu_vls_printf(logstr, " N %zu", arbn->neqn);
	for (i = 0; i < arbn->neqn; i++) {
	    bu_vls_printf(logstr, " P%zu {%.25g %.25g %.25g %.25g}", i,
			  V4ARGS(arbn->eqn[i]));
	}
    } else if (BU_STR_EQUAL(attr, "N")) {
	bu_vls_printf(logstr, "%zu", arbn->neqn);
    } else if (BU_STR_EQUAL(attr, "P")) {
	for (i = 0; i < arbn->neqn; i++) {
	    bu_vls_printf(logstr, " P%zu {%.25g %.25g %.25g %.25g}", i,
			  V4ARGS(arbn->eqn[i]));
	}
    } else if (attr[0] == 'P') {
	if (isdigit((int)attr[1]) == 0) {
	    bu_vls_printf(logstr, "ERROR: Illegal plane number\n");
	    return BRLCAD_ERROR;
	}

	val = atol(&attr[1]);
	if (val < 0 || (size_t)val >= arbn->neqn) {
	    bu_vls_printf(logstr, "ERROR: Illegal plane number [%ld]\n", val);
	    return BRLCAD_ERROR;
	}
	i = (size_t)val;

	bu_vls_printf(logstr, "%.25g %.25g %.25g %.25g", V4ARGS(arbn->eqn[i]));
    } else {
	bu_vls_printf(logstr, "ERROR: Unknown attribute, choices are N, P, or P#\n");
	return BRLCAD_ERROR;
    }

    return BRLCAD_OK;
}
Example #11
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;
}
Example #12
0
/**
 * Given a pointer to an internal GED database object, mirror the
 * object's values about the given transformation matrix.
 */
int
rt_arbn_mirror(struct rt_db_internal *ip, register const plane_t plane)
{
    struct rt_arbn_internal *arbn;

    size_t i;
    mat_t mirmat;
    mat_t rmat;
    mat_t temp;
    vect_t nvec;
    vect_t xvec;
    vect_t mirror_dir;
    point_t mirror_pt;
    fastf_t ang;

    static point_t origin = {0.0, 0.0, 0.0};

    RT_CK_DB_INTERNAL(ip);

    arbn = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(arbn);

    MAT_IDN(mirmat);

    VMOVE(mirror_dir, plane);
    VSCALE(mirror_pt, plane, plane[W]);

    /* Build mirror transform matrix, for those who need it. */
    /* First, perform a mirror down the X axis */
    mirmat[0] = -1.0;

    /* Create the rotation matrix */
    VSET(xvec, 1, 0, 0);
    VCROSS(nvec, xvec, mirror_dir);
    VUNITIZE(nvec);
    ang = -acos(VDOT(xvec, mirror_dir));
    bn_mat_arb_rot(rmat, origin, nvec, ang*2.0);

    /* Add the rotation to mirmat */
    MAT_COPY(temp, mirmat);
    bn_mat_mul(mirmat, temp, rmat);

    /* Add the translation to mirmat */
    mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X];
    mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y];
    mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z];

    for (i=0; i<arbn->neqn; i++) {
	point_t orig_pt;
	point_t pt;
	vect_t norm;
	fastf_t factor;

	/* unitize the plane equation first */
	factor = 1.0 / MAGNITUDE(arbn->eqn[i]);
	VSCALE(arbn->eqn[i], arbn->eqn[i], factor);
	arbn->eqn[i][W] = arbn->eqn[i][W] * factor;

	/* Pick a point on the original halfspace */
	VSCALE(orig_pt, arbn->eqn[i], arbn->eqn[i][W]);

	/* Transform the point, and the normal */
	MAT4X3VEC(norm, mirmat, arbn->eqn[i]);
	MAT4X3PNT(pt, mirmat, orig_pt);

	/* Measure new distance from origin to new point */
	VUNITIZE(norm);
	VMOVE(arbn->eqn[i], norm);
	arbn->eqn[i][W] = VDOT(pt, norm);
    }

    return 0;
}
Example #13
0
/**
 * "Tessellate" an ARB into an NMG data structure.
 * Purely a mechanical transformation of one faceted object
 * into another.
 *
 * Returns -
 * -1 failure
 *  0 OK.  *r points to nmgregion that holds this tessellation.
 */
int
rt_arbn_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol)
{
    struct rt_arbn_internal *aip;
    struct shell *s;
    struct faceuse **fu;		/* array of faceuses */
    size_t nverts;		/* maximum possible number of vertices = neqn!/(3!(neqn-3)! */
    size_t point_count = 0;	/* actual number of vertices */
    size_t face_count = 0;	/* actual number of faces built */
    size_t i, j, k, l, n;
    struct arbn_pts *pts;
    struct arbn_edges *edges;		/* A list of edges for each plane eqn (each face) */
    size_t *edge_count;	/* number of edges for each face */
    size_t max_edge_count; /* maximum number of edges for any face */
    struct vertex **verts;	/* Array of pointers to vertex structs */
    struct vertex ***loop_verts;	/* Array of pointers to vertex structs to pass to nmg_cmface */

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    /* Allocate memory for the vertices */
    nverts = aip->neqn * (aip->neqn-1) * (aip->neqn-2) / 6;
    pts = (struct arbn_pts *)bu_calloc(nverts, sizeof(struct arbn_pts), "rt_arbn_tess: pts");

    /* Allocate memory for arbn_edges */
    edges = (struct arbn_edges *)bu_calloc(aip->neqn*aip->neqn, sizeof(struct arbn_edges) ,
					   "rt_arbn_tess: edges");
    edge_count = (size_t *)bu_calloc(aip->neqn, sizeof(size_t), "rt_arbn_tess: edge_count");

    /* Allocate memory for faceuses */
    fu = (struct faceuse **)bu_calloc(aip->neqn, sizeof(struct faceuse *), "rt_arbn_tess: fu");

    /* Calculate all vertices */
    for (i = 0; i < aip->neqn; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    for (k = j + 1; k < aip->neqn; k++) {
		int keep_point = 1;

		if (bn_mkpoint_3planes(pts[point_count].pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]))
		    continue;

		for (l = 0; l < aip->neqn; l++) {
		    if (l == i || l == j || l == k)
			continue;
		    if (DIST_PT_PLANE(pts[point_count].pt, aip->eqn[l]) > tol->dist) {
			keep_point = 0;
			break;
		    }
		}
		if (keep_point) {
		    pts[point_count].plane_no[0] = i;
		    pts[point_count].plane_no[1] = j;
		    pts[point_count].plane_no[2] = k;
		    point_count++;
		}
	    }
	}
    }

    /* Allocate memory for the NMG vertex pointers */
    verts = (struct vertex **)bu_calloc(point_count, sizeof(struct vertex *) ,
					"rt_arbn_tess: verts");

    /* Associate points with vertices */
    for (i = 0; i < point_count; i++)
	pts[i].vp = &verts[i];

    /* Check for duplicate points */
    for (i = 0; i < point_count; i++) {
	for (j = i + 1; j < point_count; j++) {
	    if (DIST_PT_PT_SQ(pts[i].pt, pts[j].pt) < tol->dist_sq) {
		/* These two points should point to the same vertex */
		pts[j].vp = pts[i].vp;
	    }
	}
    }

    /* Make list of edges for each face */
    for (i = 0; i < aip->neqn; i++) {
	/* look for a point that lies in this face */
	for (j = 0; j < point_count; j++) {
	    if (pts[j].plane_no[0] != (int)i
		&& pts[j].plane_no[1] != (int)i
		&& pts[j].plane_no[2] != (int)i)
		continue;

	    /* look for another point that shares plane "i" and another with this one */
	    for (k = j + 1; k < point_count; k++) {
		size_t match = (size_t)-1;
		size_t pt1, pt2;
		int duplicate = 0;

		/* skip points not on plane "i" */
		if (pts[k].plane_no[0] != (int)i
		    && pts[k].plane_no[1] != (int)i
		    && pts[k].plane_no[2] != (int)i)
		    continue;

		for (l = 0; l < 3; l++) {
		    for (n = 0; n < 3; n++) {
			if (pts[j].plane_no[l] == pts[k].plane_no[n]
			    && pts[j].plane_no[l] != (int)i) {
			    match = pts[j].plane_no[l];
			    break;
			}
		    }
		    if (match != (size_t)-1)
			break;
		}

		if (match == (size_t)-1)
		    continue;

		/* convert equivalent points to lowest point number */
		pt1 = j;
		pt2 = k;
		for (l = 0; l < pt1; l++) {
		    if (pts[pt1].vp == pts[l].vp) {
			pt1 = l;
			break;
		    }
		}
		for (l = 0; l < pt2; l++) {
		    if (pts[pt2].vp == pts[l].vp) {
			pt2 = l;
			break;
		    }
		}

		/* skip null edges */
		if (pt1 == pt2)
		    continue;

		/* check for duplicate edge */
		for (l = 0; l < edge_count[i]; l++) {
		    if ((edges[LOC(i, l)].v1_no == (int)pt1
			 && edges[LOC(i, l)].v2_no == (int)pt2)
			|| (edges[LOC(i, l)].v2_no == (int)pt1
			    && edges[LOC(i, l)].v1_no == (int)pt2))
		    {
			duplicate = 1;
			break;
		    }
		}
		if (duplicate)
		    continue;

		/* found an edge belonging to faces "i" and "match" */
		if (edge_count[i] == aip->neqn) {
		    bu_log("Too many edges found for one face\n");
		    goto fail;
		}
		edges[LOC(i, edge_count[i])].v1_no = pt1;
		edges[LOC(i, edge_count[i])].v2_no = pt2;
		edge_count[i]++;
	    }
	}
    }

    /* for each face, sort the list of edges into a loop */
    Sort_edges(edges, edge_count, aip);

    /* Get max number of edges for any face */
    max_edge_count = 0;
    for (i = 0; i < aip->neqn; i++)
	if (edge_count[i] > max_edge_count)
	    max_edge_count = edge_count[i];

    /* Allocate memory for array to pass to nmg_cmface */
    loop_verts = (struct vertex ***) bu_calloc(max_edge_count, sizeof(struct vertex **) ,
					       "rt_arbn_tess: loop_verts");

    *r = nmg_mrsv(m);	/* Make region, empty shell, vertex */
    s = BU_LIST_FIRST(shell, &(*r)->s_hd);

    /* Make the faces */
    for (i = 0; i < aip->neqn; i++) {
	int loop_length = 0;

	for (j = 0; j < edge_count[i]; j++) {
	    /* skip zero length edges */
	    if (pts[edges[LOC(i, j)].v1_no].vp == pts[edges[LOC(i, j)].v2_no].vp)
		continue;

	    /* put vertex pointers into loop_verts array */
	    loop_verts[loop_length] = pts[edges[LOC(i, j)].v2_no].vp;
	    loop_length++;
	}

	/* Make the face if there is are least 3 vertices */
	if (loop_length > 2)
	    fu[face_count++] = nmg_cmface(s, loop_verts, loop_length);
    }

    /* Associate vertex geometry */
    for (i = 0; i < point_count; i++) {
	if (!(*pts[i].vp))
	    continue;

	if ((*pts[i].vp)->vg_p)
	    continue;

	nmg_vertex_gv(*pts[i].vp, pts[i].pt);
    }

    bu_free((char *)pts, "rt_arbn_tess: pts");
    bu_free((char *)edges, "rt_arbn_tess: edges");
    bu_free((char *)edge_count, "rt_arbn_tess: edge_count");
    bu_free((char *)verts, "rt_arbn_tess: verts");
    bu_free((char *)loop_verts, "rt_arbn_tess: loop_verts");

    /* Associate face geometry */
    for (i = 0; i < face_count; i++) {
	if (nmg_fu_planeeqn(fu[i], tol)) {
	    bu_log("Failed to calculate face plane equation\n");
	    bu_free((char *)fu, "rt_arbn_tess: fu");
	    nmg_kr(*r);
	    *r = (struct nmgregion *)NULL;
	    return -1;
	}
    }

    bu_free((char *)fu, "rt_arbn_tess: fu");

    nmg_fix_normals(s, tol);

    (void)nmg_mark_edges_real(&s->l.magic);

    /* Compute "geometry" for region and shell */
    nmg_region_a(*r, tol);

    return 0;

fail:
    bu_free((char *)pts, "rt_arbn_tess: pts");
    bu_free((char *)edges, "rt_arbn_tess: edges");
    bu_free((char *)edge_count, "rt_arbn_tess: edge_count");
    bu_free((char *)verts, "rt_arbn_tess: verts");
    return -1;
}
Example #14
0
/**
 * Brute force through all possible plane intersections.
 * Generate all edge lines, then intersect the line with all
 * the other faces to find the vertices on that line.
 * If the geometry is correct, there will be no more than two.
 * While not the fastest strategy, this will produce an accurate
 * plot without requiring extra bookkeeping.
 * Note that the vectors will be drawn in no special order.
 */
int
rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info))
{
    struct rt_arbn_internal *aip;
    size_t i;
    size_t j;
    size_t k;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    for (i = 0; i < aip->neqn - 1; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    double dot;
	    int point_count;	/* # points on this line */
	    point_t a, b;		/* start and end points */
	    vect_t dist;

	    VSETALL(a, 0);
	    VSETALL(b, 0);

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with all other planes */
	    point_count = 0;
	    for (k = 0; k < aip->neqn; k++) {
		size_t m;
		point_t pt;
		size_t next_k;

		next_k = 0;

		if (k == i || k == j) continue;
		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m) continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}

		if (next_k != 0) continue;

		if (point_count <= 0) {
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
		    VMOVE(a, pt);
		} else if (point_count == 1) {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
		    VMOVE(b, pt);
		} else {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    VSUB2(dist, pt, b);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n",
			   point_count+1,
			   i, j);
		    VPRINT(" a", a);
		    VPRINT(" b", b);
		    VPRINT("pt", pt);
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);	/* draw it */
		}
		point_count++;
	    }
	    /* Point counts of 1 are (generally) not harmful,
	     * occurring on pyramid peaks and the like.
	     */
	}
    }
    return 0;
}
Example #15
0
/**
 * Routine to modify an arbn via the "db adjust" command
 *
 * Legal parameters are:
 *		"N" - adjust the number of planes (new ones will be zeroed)
 *		"P" - adjust the entire list of planes
 *		"P#" - adjust a specific plane (0 based)
 *		"P+" - add a new plane to the list of planes
 */
int
rt_arbn_adjust(struct bu_vls *logstr, struct rt_db_internal *intern, int argc, const char **argv)
{
    struct rt_arbn_internal *arbn;
    unsigned char *c;
    int len;
    size_t i, j;
    long val;
    fastf_t *new_planes;
    fastf_t *array;

    RT_CK_DB_INTERNAL(intern);

    arbn = (struct rt_arbn_internal *)intern->idb_ptr;
    RT_ARBN_CK_MAGIC(arbn);

    while (argc >= 2) {
	if (BU_STR_EQUAL(argv[0], "N")) {
	    val = atol(argv[1]);
	    if (val < 0) {
		bu_vls_printf(logstr, "ERROR: number of planes [%ld] must be greater than 0\n", val);
		val = 1;
	    }

	    i = (size_t)val;
	    if (i == arbn->neqn)
		goto cont;

	    arbn->eqn = (plane_t *)bu_realloc(arbn->eqn,
					      i * sizeof(plane_t),
					      "arbn->eqn");
	    for (j=arbn->neqn; j<i; j++) {
		HSETALL(arbn->eqn[j], 0.0);
	    }
	    arbn->neqn = i;

	} else if (BU_STR_EQUAL(argv[0], "P")) {
	    /* eliminate all the '{' and '}' chars */
	    c = (unsigned char *)argv[1];
	    while (*c != '\0') {
		if (*c == '{' || *c == '}')
		    *c = ' ';
		c++;
	    }
	    len = 0;
	    (void)tcl_list_to_fastf_array(brlcad_interp, argv[1], &new_planes, &len);

	    if (len%ELEMENTS_PER_PLANE) {
		bu_vls_printf(logstr,
			      "ERROR: Incorrect number of plane coefficients\n");
		if (len)
		    bu_free((char *)new_planes, "new_planes");
		return BRLCAD_ERROR;
	    }
	    if (arbn->eqn)
		bu_free((char *)arbn->eqn, "arbn->eqn");
	    arbn->eqn = (plane_t *)new_planes;
	    arbn->neqn = (size_t)len / ELEMENTS_PER_PLANE;
	    for (i = 0; i < arbn->neqn; i++)
		VUNITIZE(arbn->eqn[i]);
	} else if (argv[0][0] == 'P') {
	    if (argv[0][1] == '+') {
		i = arbn->neqn;
		arbn->neqn++;
		arbn->eqn = (plane_t *)bu_realloc(arbn->eqn,
						  (arbn->neqn) * sizeof(plane_t),
						  "arbn->eqn");
	    } else if (isdigit((int)argv[0][1])) {
		i = atoi(&argv[0][1]);
	    } else {
		bu_vls_printf(logstr,
			      "ERROR: illegal argument, choices are P, P#, P+, or N\n");
		return TCL_ERROR;
	    }
	    if (i >= arbn->neqn) {
		bu_vls_printf(logstr, "ERROR: plane number out of range\n");
		return BRLCAD_ERROR;
	    }
	    len = ELEMENTS_PER_PLANE;
	    array = (fastf_t *)&arbn->eqn[i];
	    if (tcl_list_to_fastf_array(brlcad_interp, argv[1],
					&array, &len) != ELEMENTS_PER_PLANE) {
		bu_vls_printf(logstr,
			      "ERROR: incorrect number of coefficients for a plane\n");
		return BRLCAD_ERROR;
	    }
	    VUNITIZE(arbn->eqn[i]);
	} else {
	    bu_vls_printf(logstr,
			  "ERROR: illegal argument, choices are P, P#, P+, or N\n");
	    return BRLCAD_ERROR;
	}
    cont:
	argc -= 2;
	argv += 2;
    }
    return BRLCAD_OK;
}
Example #16
0
/**
 * Returns -
 *  0 OK
 * !0 failure
 */
int
rt_arbn_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
{
    struct rt_arbn_internal *aip;
    vect_t work;
    fastf_t f;
    size_t i;
    size_t j;
    size_t k;
    int *used = (int *)0;	/* plane eqn use count */
    const struct bn_tol *tol = &rtip->rti_tol;

    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    used = (int *)bu_malloc(aip->neqn*sizeof(int), "arbn used[]");

    /*
     * ARBN must be convex.  Test for concavity.
     * Byproduct is an enumeration of all the vertices,
     * which are used to make the bounding RPP.  No need
     * to call the bbox routine, as the work must be duplicated
     * here to count faces.
     */

    /* Zero face use counts
     * and make sure normal vectors are unit vectors
     */
    for (i = 0; i < aip->neqn; i++) {
	double normalLen = MAGNITUDE(aip->eqn[i]);
	double scale;
	if (ZERO(normalLen)) {
	    bu_log("arbn has zero length normal vector\n");
	    return 1;
	}
	scale = 1.0 / normalLen;
	HSCALE(aip->eqn[i], aip->eqn[i], scale);
	used[i] = 0;
    }
    for (i = 0; i < aip->neqn-2; i++) {
	for (j=i+1; j<aip->neqn-1; j++) {
	    double dot;

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with higher numbered planes */
	    for (k=j+1; k<aip->neqn; k++) {
		size_t m;
		size_t next_k;
		point_t pt;

		next_k = 0;

		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m)
			continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}
		if (next_k != 0) continue;

		VMINMAX(stp->st_min, stp->st_max, pt);

		/* Increment "face used" counts */
		used[i]++;
		used[j]++;
		used[k]++;
	    }
	}
    }

    /* If any planes were not used, then arbn is not convex */
    for (i = 0; i < aip->neqn; i++) {
	if (used[i] != 0) continue;	/* face was used */
	bu_log("arbn(%s) face %zu unused, solid is not convex\n",
	       stp->st_name, i);
	bu_free((char *)used, "arbn used[]");
	return -1;		/* BAD */
    }
    bu_free((char *)used, "arbn used[]");

    stp->st_specific = (void *)aip;
    ip->idb_ptr = ((void *)0);	/* indicate we stole it */

    VADD2SCALE(stp->st_center, stp->st_min, stp->st_max, 0.5);
    VSUB2SCALE(work, stp->st_max, stp->st_min, 0.5);

    f = work[X];
    if (work[Y] > f) f = work[Y];
    if (work[Z] > f) f = work[Z];
    stp->st_aradius = f;
    stp->st_bradius = MAGNITUDE(work);
    return 0;			/* OK */
}