Exemplo n.º 1
0
/*
 *			R T _ N U R B _ B E Z I E R
 *
 *  Given a single snurb, if it is in Bezier form,
 *  duplicate the snurb, and enqueue it on the bezier_hd list.
 *  If the original snurb is NOT in Bezier form,
 *  subdivide it a set of snurbs which are,
 *  each of which are enqueued on the bezier_hd list.
 *
 *  In either case, the original surface remains untouched.
 *
 *  Returns -
 *	0	Surface splitting was done.
 *	1	Original surface was Bezier, only a copy was done.
 */
int
rt_nurb_bezier(struct bu_list *bezier_hd, const struct face_g_snurb *orig_surf, struct resource *res)
{
    struct face_g_snurb	*s;
    int		dir;
    struct bu_list	todo;

    NMG_CK_SNURB(orig_surf);

    if ( (dir = rt_bez_check( orig_surf )) == -1)  {
	s = rt_nurb_scopy( orig_surf, res );
	BU_LIST_APPEND( bezier_hd, &s->l );
	return 1;	/* Was already Bezier, nothing done */
    }

    BU_LIST_INIT( &todo );
    rt_nurb_s_split( &todo, orig_surf, dir, res );

    while ( BU_LIST_WHILE( s, face_g_snurb, &todo ) )  {
	if ( (dir = rt_bez_check(s)) == -1)  {
	    /* This snurb is now a Bezier */
	    BU_LIST_DEQUEUE( &s->l );
	    BU_LIST_APPEND( bezier_hd, &s->l );
	} else {
	    /* Split, and keep going */
	    BU_LIST_DEQUEUE( &s->l );
	    rt_nurb_s_split( &todo, s, dir, res );
	    rt_nurb_free_snurb(s, res);
	}
    }
    return 0;		/* Bezier snurbs on bezier_hd list */
}
Exemplo n.º 2
0
HIDDEN struct bu_cmdhist_obj *
cho_open(ClientData UNUSED(clientData), Tcl_Interp *interp, const char *name)
{
    struct bu_cmdhist_obj *chop;

    /* check to see if command history object exists */
    for (BU_LIST_FOR(chop, bu_cmdhist_obj, &HeadCmdHistObj.l)) {
	if (BU_STR_EQUAL(name, bu_vls_addr(&chop->cho_name))) {
	    Tcl_AppendResult(interp, "ch_open: ", name,
			     " exists.\n", (char *)NULL);
	    return BU_CMDHIST_OBJ_NULL;
	}
    }

    BU_GET(chop, struct bu_cmdhist_obj);
    bu_vls_init(&chop->cho_name);
    bu_vls_strcpy(&chop->cho_name, name);
    BU_LIST_INIT(&chop->cho_head.l);
    bu_vls_init(&chop->cho_head.h_command);
    chop->cho_head.h_start.tv_sec = chop->cho_head.h_start.tv_usec =
	chop->cho_head.h_finish.tv_sec = chop->cho_head.h_finish.tv_usec = 0L;
    chop->cho_head.h_status = TCL_OK;
    chop->cho_curr = &chop->cho_head;

    BU_LIST_APPEND(&HeadCmdHistObj.l, &chop->l);
    return chop;
}
void
new_image(const struct bu_structparse *UNUSED(sdp),
	  const char *UNUSED(name),
	  void *base,
	  const char *UNUSED(value),
	  void *UNUSED(data))
{
    struct bbd_specific *bbd_sp = (struct bbd_specific *)base;
    struct bbd_img *bbdi;

    /* XXX - looks like we don't release this memory */
    BU_ALLOC(bbdi, struct bbd_img);

    bbdi->img_mf = bu_open_mapped_file_with_path(
	bbd_sp->rtip->rti_dbip->dbi_filepath,
	bu_vls_addr(&bbd_sp->img_filename),
	NULL);

    if (!bbdi->img_mf) {
	bu_log("error opening image %s\n", bu_vls_addr(&bbd_sp->img_filename));
	bu_bomb("");
    }
    BU_CK_MAPPED_FILE(bbdi->img_mf);

    bbdi->img_width = bbd_sp->img_width;
    bbdi->img_width = bbd_sp->img_height;

    BU_LIST_APPEND(&bbd_sp->imgs, &(bbdi->l));
    bbd_sp->img_count++;

}
Exemplo n.º 4
0
void
nurb_c_to_bezier(struct bu_list *clist, struct edge_g_cnurb *crv)
{
    fastf_t knot_min, knot_max;
    int i;
    struct edge_g_cnurb *crv1, *crv_copy;
    int done;

    /* make a copy of original curve */
    crv_copy = rt_nurb_crv_copy( crv );

    /* split curve at each knot value */
    done = 0;
    while ( !done )
    {
	fastf_t split;

	knot_min = crv_copy->k.knots[0];
	knot_max = crv_copy->k.knots[crv_copy->k.k_size-1];

	split = MAX_FASTF;
	for ( i=1; i<crv_copy->k.k_size-1; i++ )
	{
	    if ( crv_copy->k.knots[i] != knot_min && crv_copy->k.knots[i] != knot_max )
	    {
		split = crv_copy->k.knots[i];
		break;
	    }
	}

	if ( split == MAX_FASTF )
	{
	    done = 1;
	    BU_LIST_APPEND( clist, &crv_copy->l );
	    break;
	}

	crv1 = rt_nurb_c_xsplit( crv_copy, split );

	rt_nurb_free_cnurb( crv_copy );
	crv_copy = BU_LIST_PNEXT( edge_g_cnurb, &crv1->l );
	BU_LIST_DEQUEUE( &crv_copy->l );

	BU_LIST_APPEND( clist, &crv1->l );
    }
}
int
rt_gen_conic(struct xrays *rays, const struct xray *center_ray,
	     fastf_t theta, vect_t up_vector, int rays_per_radius)
{
    int count = 0;

    point_t start;
    vect_t orig_dir;

    fastf_t x, y;

    /* Setting radius to tan(theta) works because, as shown in the
     * following diagram, the ray that starts at the given point and
     * passes through orig_dir + (radius in any orthogonal direction)
     * has an angle of theta with the original ray; when the
     * resulting vector is normalized, the angle is preserved.
     */
    fastf_t radius = tan(theta);
    fastf_t rsq = radius * radius; /* radius-squared, for use in the loop */

    fastf_t gridsize = 2 * radius / (rays_per_radius - 1);

    vect_t a_dir, b_dir;

    register struct xrays *xrayp;

    VMOVE(start, center_ray->r_pt);
    VMOVE(orig_dir, center_ray->r_dir);

    /* Create vectors a_dir, b_dir that are orthogonal to orig_dir. */
    VMOVE(b_dir, up_vector);
    VUNITIZE(b_dir);

    VCROSS(a_dir, orig_dir, up_vector);
    VUNITIZE(a_dir);

    for (y = -radius; y <= radius; y += gridsize) {
	vect_t tmp;
	printf("y:%f\n", y);
	VSCALE(tmp, b_dir, y);
	printf("y_partofit: %f,%f,%f\n", V3ARGS(tmp));
	for (x = -radius; x <= radius; x += gridsize) {
	    if (((x*x)/rsq + (y*y)/rsq) <= 1) {
		BU_ALLOC(xrayp, struct xrays);
		VMOVE(xrayp->ray.r_pt, start);
		VJOIN2(xrayp->ray.r_dir, orig_dir, x, a_dir, y, b_dir);
		VUNITIZE(xrayp->ray.r_dir);
		xrayp->ray.index = count++;
		xrayp->ray.magic = RT_RAY_MAGIC;
		BU_LIST_APPEND(&rays->l, &xrayp->l);
	    }
	}
    }
    return count;
}
Exemplo n.º 6
0
void
bu_add_hook(struct bu_hook_list *hlp, bu_hook_t func, genptr_t clientdata)
{
    struct bu_hook_list *new_hook;

    BU_GETSTRUCT(new_hook, bu_hook_list);
    new_hook->hookfunc = func;
    new_hook->clientdata = clientdata;
    new_hook->l.magic = BU_HOOK_LIST_MAGIC;
    BU_LIST_APPEND(&hlp->l, &new_hook->l);
}
Exemplo n.º 7
0
/**
 * rt_nurb_c_xsplit()
 *
 * Split a NURB curve by inserting a multiple knot and return the
 * result of the two curves.
 *
 * Algorithm:
 *
 * Insert a multiple knot of the curve order. A parameter is give for
 * the knot value for which the curve will be split.
 */
struct edge_g_cnurb *
rt_nurb_c_xsplit(struct edge_g_cnurb *crv, fastf_t param)
{
    struct knot_vector new_kv;
    struct oslo_mat * oslo;
    int k_index;
    struct edge_g_cnurb * crv1, * crv2;
    int coords;

    NMG_CK_CNURB(crv);

    coords = RT_NURB_EXTRACT_COORDS(crv->pt_type),

	k_index = crv->order;
    rt_nurb_kvmult(&new_kv, &crv->k, crv->order, param, (struct resource *)NULL);

    oslo = (struct oslo_mat *)
	rt_nurb_calc_oslo(crv->order, &crv->k, &new_kv, (struct resource *)NULL);

    GET_CNURB(crv1);
    crv1->order  = crv->order;
    rt_nurb_kvextract(&crv1->k, &new_kv, 0, k_index + crv->order, (struct resource *)NULL);
    crv1->pt_type = crv->pt_type;
    crv1->c_size = crv1->k.k_size - crv1->order;
    crv1->ctl_points = (fastf_t *)
	bu_malloc(sizeof(fastf_t) * crv1->c_size *
		  RT_NURB_EXTRACT_COORDS(crv1->pt_type),
		  "rt_nurb_c_xsplit: crv1 control points");

    GET_CNURB(crv2);
    crv2->order  = crv->order;
    rt_nurb_kvextract(&crv2->k, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
    crv2->pt_type = crv->pt_type;
    crv2->c_size = crv2->k.k_size - crv2->order;
    crv2->ctl_points = (fastf_t *)
	bu_malloc(sizeof(fastf_t) * crv2->c_size *
		  RT_NURB_EXTRACT_COORDS(crv2->pt_type),
		  "rt_nurb_c_xsplit: crv2 row mesh control points");

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv1->ctl_points,
		     coords, coords, 0, k_index, crv->pt_type);

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv2->ctl_points,
		     coords, coords, k_index, new_kv.k_size - crv2->order,
		     crv2->pt_type);

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    bu_free((char *) new_kv.knots, "rt_nurb_c_xsplit: new_kv.knots");

    BU_LIST_APPEND(&crv1->l, &crv2->l);
    return crv1;
}
Exemplo n.º 8
0
/**
 * Classify a point vs a vertex (touching/missed)
 */
static int
nmg_class_pt_vu(struct fpi *fpi, struct vertexuse *vu)
{
    vect_t delta;
    struct ve_dist *ved;

    NMG_CK_VERTEXUSE(vu);

    /* see if we've classified this vertex WRT the point already */
    for (BU_LIST_FOR(ved, ve_dist, &fpi->ve_dh)) {
	NMG_CK_VED(ved);
	if (ved->magic_p == &vu->v_p->magic) {
	    goto found;
	}
    }

    /* if we get here, we didn't find the vertex in the list of
     * previously classified geometry.  Create an entry in the
     * face's list of processed geometry.
     */
    VSUB2(delta, vu->v_p->vg_p->coord, fpi->pt);

    BU_ALLOC(ved, struct ve_dist);
    ved->magic_p = &vu->v_p->magic;
    ved->dist = MAGNITUDE(delta);
    if (ved->dist < fpi->tol->dist_sq) {
	ved->status = NMG_FPI_TOUCHED;
	if (fpi->hits == NMG_FPI_PERGEOM) {
	    /* need to cast vu_func pointer for actual use as a function */
	    void (*cfp)(struct vertexuse *, point_t, const char*);
	    cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func;
	    cfp(vu, fpi->pt, fpi->priv);
	}
    } else ved->status = NMG_FPI_MISSED;

    ved->v1 = ved->v2 = vu->v_p;

    BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC);
    BU_LIST_APPEND(&fpi->ve_dh, &ved->l);
found:

    if (fpi->vu_func  &&
	ved->status == NMG_FPI_TOUCHED &&
	fpi->hits == NMG_FPI_PERUSE) {
	/* need to cast vu_func pointer for actual use as a function */
	void (*cfp)(struct vertexuse *, point_t, const char*);
	cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func;
	cfp(vu, fpi->pt, fpi->priv);
    }

    return ved->status;
}
int
rt_gen_frustum(struct xrays *rays, const struct xray *center_ray,
	       const vect_t a_vec, const vect_t b_vec,
	       const fastf_t a_theta, const fastf_t b_theta,
	       const fastf_t a_num, const fastf_t UNUSED(b_num))
{
    int count = 0;

    point_t start;
    vect_t orig_dir;

    fastf_t x, y;

    fastf_t a_length = tan(a_theta);
    fastf_t b_length = tan(b_theta);
    fastf_t a_inc = 2 * a_length / (a_num - 1);

    vect_t a_dir, b_dir;

    register struct xrays *xrayp;

    VMOVE(start, center_ray->r_pt);
    VMOVE(orig_dir, center_ray->r_dir);

    VMOVE(a_dir, a_vec);
    VUNITIZE(a_dir);
    VMOVE(b_dir, b_vec);
    VUNITIZE(b_dir);

    /* This adds BN_TOL_DIST to the *_length variables in the
     * condition because in some cases, floating-point problems can
     * make extremely close numbers compare incorrectly. */
    for (y = -b_length; y <= b_length + BN_TOL_DIST;) {
	for (x = -a_length; x <= a_length + BN_TOL_DIST; x += a_inc) {
	    BU_ALLOC(xrayp, struct xrays);
	    VMOVE(xrayp->ray.r_pt, start);
	    VJOIN2(xrayp->ray.r_dir, orig_dir, x, a_dir, y, b_dir);
	    VUNITIZE(xrayp->ray.r_dir);
	    xrayp->ray.index = count++;
	    xrayp->ray.magic = RT_RAY_MAGIC;
	    BU_LIST_APPEND(&rays->l, &xrayp->l);
	}
    }
    return count;
}
int
rt_gen_elliptical_grid(struct xrays *rays, const struct xray *center_ray, const fastf_t *avec, const fastf_t *bvec, fastf_t gridsize)
{
    register struct xrays *xrayp;
    int count = 0;
    point_t C;
    vect_t dir;
    vect_t a_dir;
    vect_t b_dir;

    fastf_t a = MAGNITUDE(avec);
    fastf_t b = MAGNITUDE(bvec);
    fastf_t x, y;

    int acpr = a / gridsize;
    int bcpr = b / gridsize;

    VMOVE(a_dir, avec);
    VUNITIZE(a_dir);

    VMOVE(b_dir, bvec);
    VUNITIZE(b_dir);

    VMOVE(C, center_ray->r_pt);
    VMOVE(dir, center_ray->r_dir);
    /* make sure avec perpendicular to bvec perpendicular to ray direction */
    BU_ASSERT(NEAR_ZERO(VDOT(avec, bvec), VUNITIZE_TOL));
    BU_ASSERT(NEAR_ZERO(VDOT(avec, dir), VUNITIZE_TOL));

    for (y=gridsize * (-bcpr); y <= b; y=y+gridsize) {
	for (x= gridsize * (-acpr); x <= a; x=x+gridsize) {
	    if (((x*x)/(a*a) + (y*y)/(b*b)) < 1) {
		BU_ALLOC(xrayp, struct xrays);
		VJOIN2(xrayp->ray.r_pt, C, x, a_dir, y, b_dir);
		VMOVE(xrayp->ray.r_dir, dir);
		xrayp->ray.index = count++;
		xrayp->ray.magic = RT_RAY_MAGIC;
		BU_LIST_APPEND(&rays->l, &xrayp->l);
	    }
	}
    }
    return count;
}
Exemplo n.º 11
0
void
bu_log_add_hook(bu_hook_t func, genptr_t clientdata)
{
#if 0
    struct bu_hook_list *toadd;

    /* Grab a hunk of memory for a new node, and put it at the head of the
       list */

    BU_GETSTRUCT(toadd, bu_hook_list);
    toadd->hookfunc = func;
    toadd->clientdata = clientdata;
    toadd->l.magic = BU_HOOK_LIST_MAGIC;

    BU_LIST_APPEND( &(bu_log_hook_list.l), &(toadd->l) );
#else
    bu_add_hook(&bu_log_hook_list, func, clientdata);
#endif
}
int rt_gen_rect(struct xrays *rays, const struct xray *center_ray,
		const vect_t a_vec, const vect_t b_vec,
		const fastf_t da, const fastf_t db)
{
    int count = 0;

    point_t orig_start;
    vect_t dir;

    fastf_t x, y;

    fastf_t a_length = MAGNITUDE(a_vec);
    fastf_t b_length = MAGNITUDE(b_vec);

    vect_t a_dir;
    vect_t b_dir;

    register struct xrays *xrayp;

    VMOVE(orig_start, center_ray->r_pt);
    VMOVE(dir, center_ray->r_dir);

    VMOVE(a_dir, a_vec);
    VUNITIZE(a_dir);

    VMOVE(b_dir, b_vec);
    VUNITIZE(b_dir);

    for (y = -b_length; y <= b_length; y += db) {
	for (x = -a_length; x <= a_length; x += da) {
	    BU_ALLOC(xrayp, struct xrays);
	    VJOIN2(xrayp->ray.r_pt, orig_start, x, a_dir, y, b_dir);
	    VMOVE(xrayp->ray.r_dir, dir);
	    xrayp->ray.index = count++;
	    xrayp->ray.magic = RT_RAY_MAGIC;
	    BU_LIST_APPEND(&rays->l, &xrayp->l);
	}
    }
    return count;
}
Exemplo n.º 13
0
/*
 *  We try and clip a curve so that it can be either Case A, or Case C.
 *  Sometimes one of the curves is still case C though, but it is much
 *  small than the original, and further clipping will either show that
 *  it is on the curve or provide all Case B or Case A curves.
 *  We try and pick the best axis to clip against, but this may not always
 *  work. One extra step that was included, that is not in the paper for
 *  curves but is for surfaces, is the fact that sometimes the curve is
 *  not clipped enough, if the maximum clip is less than .2 than we sub
 *  divide the curve in three equal parts, at .3 and .6,
 *  Subdivision is done using the Oslo Algorithm, rather than the other
 *  methods which were prossed.
 */
void
rt_clip_cnurb(struct bu_list *plist, struct edge_g_cnurb *crv, fastf_t u, fastf_t v)
{
    fastf_t ds1, dt1;
    struct _interior_line s_line, t_line;
    int axis, i;
    fastf_t umin, umax;
    int coords;
    struct edge_g_cnurb * c1, *c2, *tmp;
    fastf_t m1, m2;
    int zero_changed;
    fastf_t *ptr;
    fastf_t dist[10];

    coords = RT_NURB_EXTRACT_COORDS( crv->pt_type);

    s_line.axis = 0;	s_line.o_dist = v;
    t_line.axis = 1;	t_line.o_dist = u;

    ds1 = 0.0;
    dt1 = 0.0;

    ptr = crv->ctl_points;


    /* determine what axis to clip against */

    for ( i = 0; i < crv->c_size; i++, ptr += coords)
    {
	ds1 +=
	    fabs( rt_trim_line_pt_dist( &s_line, ptr, crv->pt_type) );
	dt1 +=
	    fabs( rt_trim_line_pt_dist( &t_line, ptr, crv->pt_type) );
    }

    if ( ds1 >= dt1 ) axis = 0; else axis = 1;

    ptr = crv->ctl_points;

    for ( i = 0; i < crv->c_size; i++)
    {
	if ( axis == 1)
	    dist[i] = rt_trim_line_pt_dist(&t_line, ptr, crv->pt_type);
	else
	    dist[i] = rt_trim_line_pt_dist(&s_line, ptr, crv->pt_type);

	ptr += coords;
    }

    /* Find the convex hull of the distances and determine the
     * minimum and maximum distance to clip against. See the
     * paper for details about this step
     */

    umin = 10e40;
    umax = -10e40;
    zero_changed = 0;

    for ( i = 0; i < crv->c_size; i++)
    {
	fastf_t d1, d2;
	fastf_t x0, x1, zero;

	if ( i == (crv->c_size -1 ) )
	{
	    d1 = dist[i];
	    d2 = dist[0];
	    x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1);
	    x1 = 0.0;
	} else
	{
	    d1 = dist[i];
	    d2 = dist[i+1];
	    x0 = (fastf_t) i / (fastf_t) (crv->c_size - 1 );
	    x1 = (i+1.0) / (crv->c_size - 1);
	}

	if ( _SIGN(d1) != _SIGN(d2) )
	{
	    zero = x0 - d1 * (x1 - x0)/ (d2-d1);
	    if ( zero <= umin)
		umin = zero * .99;
	    if ( zero >= umax)
		umax = zero * .99 + .01;
	    zero_changed = 1;
	}
    }

    if ( !zero_changed)
	return;

    /* Clip is not large enough, split in thiords and try again */

    if ( umax - umin < .2)
    {
	umin = .3; umax = .6;
    }

    /* Translate the 0.0-->1.09 clipping against the real knots */

    m1 = (crv->k.knots[0] * (1 - umin)) +
	crv->k.knots[crv->k.k_size -1] *  umin;

    m2 = (crv->k.knots[0] * (1-umax)) +
	crv->k.knots[crv->k.k_size -1] * umax;

    /* subdivide the curve */
    c1 = (struct edge_g_cnurb *) rt_nurb_c_xsplit(crv, m1);
    c2 = rt_nurb_c_xsplit((struct edge_g_cnurb *) c1->l.forw, m2);

    tmp = (struct edge_g_cnurb *) c1->l.forw;
    BU_LIST_DEQUEUE( &tmp->l);
    rt_nurb_free_cnurb( tmp );

    BU_LIST_INIT( plist );
    BU_LIST_INSERT( &c2->l, plist);
    BU_LIST_APPEND( plist, &c1->l);
}
Exemplo n.º 14
0
/**
 * Make a list of all edgeuses which are at the same distance as the
 * first element on the list.  Toss out opposing pairs of edgeuses of the
 * same edge.
 *
 */
HIDDEN void make_near_list(struct edge_info *edge_list, struct bu_list *near1, const struct bn_tol *tol)
{
    struct edge_info *ei;
    struct edge_info *ei_p;
    struct edge_info *tmp;
    fastf_t dist;

    BU_CK_LIST_HEAD(&edge_list->l);
    BU_CK_LIST_HEAD(near1);

    /* toss opposing pairs of uses of the same edge from the list */
    ei = BU_LIST_FIRST(edge_info, &edge_list->l);
    while (BU_LIST_NOT_HEAD(&ei->l, &edge_list->l)) {
	NMG_CK_EI(ei);
	ei_p = BU_LIST_FIRST(edge_info, &edge_list->l);
	while (BU_LIST_NOT_HEAD(&ei_p->l, &edge_list->l)) {
	    NMG_CK_EI(ei_p);
	    NMG_CK_VED(ei_p->ved_p);

	    /* if we've found an opposing use of the same
	     * edge toss the pair of them
	     */
	    if (ei_p->ved_p->magic_p == ei->ved_p->magic_p &&
		ei_p->eu_p->eumate_p->vu_p->v_p == ei->eu_p->vu_p->v_p &&
		ei_p->eu_p->vu_p->v_p == ei->eu_p->eumate_p->vu_p->v_p) {
		if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) {
		    bu_log("tossing edgeuse pair:\n");
		    bu_log("(%g %g %g) -> (%g %g %g)\n",
			   V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
			   V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
		    bu_log("(%g %g %g) -> (%g %g %g)\n",
			   V3ARGS(ei_p->eu_p->vu_p->v_p->vg_p->coord),
			   V3ARGS(ei_p->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
		}

		tmp = ei_p;
		ei_p = BU_LIST_PLAST(edge_info, &ei_p->l);
		BU_LIST_DEQUEUE(&tmp->l);
		bu_free((char *)tmp, "edge info struct");
		tmp = ei;
		ei = BU_LIST_PLAST(edge_info, &ei->l);
		BU_LIST_DEQUEUE(&tmp->l);
		bu_free((char *)tmp, "edge info struct");
		break;
	    }
	    ei_p = BU_LIST_PNEXT(edge_info, &ei_p->l);
	}
	ei = BU_LIST_PNEXT(edge_info, &ei->l);
    }

    if (BU_LIST_IS_EMPTY(&edge_list->l))
	return;

    ei = BU_LIST_FIRST(edge_info, &edge_list->l);
    NMG_CK_EI(ei);
    NMG_CK_VED(ei->ved_p);
    dist = ei->ved_p->dist;

    /* create "near" list with all ei's at this dist */
    for (BU_LIST_FOR(ei, edge_info, &edge_list->l)) {
	NMG_CK_EI(ei);
	NMG_CK_VED(ei->ved_p);
	if (NEAR_EQUAL(ei->ved_p->dist, dist, tol->dist_sq)) {
	    ei_p = BU_LIST_PLAST(edge_info, &ei->l);
	    BU_LIST_DEQUEUE(&ei->l);
	    BU_LIST_APPEND(near1, &ei->l);
	    ei = ei_p;
	}
    }

    if (UNLIKELY(RTG.NMG_debug & DEBUG_PT_FU)) {
	bu_log("dist %g near list\n", dist);
	for (BU_LIST_FOR(ei, edge_info, near1)) {
	    bu_log("\t(%g %g %g) -> (%g %g %g)\n",
		   V3ARGS(ei->eu_p->vu_p->v_p->vg_p->coord),
		   V3ARGS(ei->eu_p->eumate_p->vu_p->v_p->vg_p->coord));
	    bu_log("\tdist:%g class:%s status:%d\n\t\tv1(%g %g %g) v2(%g %g %g)\n",
		   ei->ved_p->dist, nmg_class_name(ei->nmg_class),
		   ei->ved_p->status,
		   V3ARGS(ei->ved_p->v1->vg_p->coord),
		   V3ARGS(ei->ved_p->v2->vg_p->coord));
	    bu_log("\tei->ved_p->magic_p=%p, ei->eu_p->vu_p=%p, ei->eu_p->eumate_p->vu_p=%p\n",
		   (void *)ei->ved_p->magic_p, (void *)ei->eu_p->vu_p, (void *)ei->eu_p->eumate_p->vu_p);
	}
    }
Exemplo n.º 15
0
/**
 * If there is no ve_dist structure for this edge, compute one and
 * add it to the list.
 *
 * Sort an edge_info structure into the loops list of edgeuse status
 */
static struct edge_info *
nmg_class_pt_eu(struct fpi *fpi, struct edgeuse *eu, struct edge_info *edge_list, const int in_or_out_only)
{
    struct bn_tol tmp_tol;
    struct edgeuse *next_eu;
    struct ve_dist *ved, *ed;
    struct edge_info *ei_p;
    struct edge_info *ei;
    pointp_t eu_pt;
    vect_t left;
    vect_t v_to_pt;
    int found_data = 0;

    NMG_CK_FPI(fpi);
    BN_CK_TOL(fpi->tol);

    if (RTG.NMG_debug & DEBUG_PT_FU) {
	bu_log("pt (%g %g %g) vs_edge (%g %g %g) (%g %g %g) (eu=%p)\n",
	       V3ARGS(fpi->pt),
	       V3ARGS(eu->vu_p->v_p->vg_p->coord),
	       V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord), (void *)eu);
    }

    /* we didn't find a ve_dist structure for this edge, so we'll
     * have to do the calculations.
     */
    tmp_tol = (*fpi->tol);
    if (in_or_out_only) {
	tmp_tol.dist = 0.0;
	tmp_tol.dist_sq = 0.0;
    }

    BU_ALLOC(ved, struct ve_dist);
    ved->magic_p = &eu->e_p->magic;
    ved->status = bn_distsq_pt3_lseg3(&ved->dist,
				      eu->vu_p->v_p->vg_p->coord,
				      eu->eumate_p->vu_p->v_p->vg_p->coord,
				      fpi->pt,
				      &tmp_tol);
    ved->v1 = eu->vu_p->v_p;
    ved->v2 = eu->eumate_p->vu_p->v_p;
    BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC);
    BU_LIST_APPEND(&fpi->ve_dh, &ved->l);
    eu_pt = ved->v1->vg_p->coord;

    if (RTG.NMG_debug & DEBUG_PT_FU) {
	bu_log("nmg_class_pt_eu: status for eu %p (%g %g %g)<->(%g %g %g) vs pt (%g %g %g) is %d\n",
	       (void *)eu, V3ARGS(eu->vu_p->v_p->vg_p->coord),
	       V3ARGS(eu->eumate_p->vu_p->v_p->vg_p->coord),
	       V3ARGS(fpi->pt), ved->status);
	bu_log("\tdist = %g\n", ved->dist);
    }


    /* Add a struct for this edgeuse to the loop's list of dist-sorted
     * edgeuses.
     */
    BU_ALLOC(ei, struct edge_info);
    ei->ved_p = ved;
    ei->eu_p = eu;
    BU_LIST_MAGIC_SET(&ei->l, NMG_EDGE_INFO_MAGIC);

    /* compute the status (ei->status) of the point WRT this edge */

    switch (ved->status) {
	case 0: /* pt is on the edge(use) */
	    ei->nmg_class = NMG_CLASS_AonBshared;
	    if (fpi->eu_func &&
		(fpi->hits == NMG_FPI_PERUSE ||
		 (fpi->hits == NMG_FPI_PERGEOM && !found_data))) {
		/* need to cast eu_func pointer for actual use as a function */
		void (*cfp)(struct edgeuse *, point_t, const char*);
		cfp = (void (*)(struct edgeuse *, point_t, const char *))fpi->eu_func;
		cfp(eu, fpi->pt, fpi->priv);
	    }
	    break;
	case 1:	/* within tolerance of endpoint at ved->v1 */
	    ei->nmg_class = NMG_CLASS_AonBshared;
	    /* add an entry for the vertex in the edge list so that
	     * other uses of this vertex will claim the point is within
	     * tolerance without re-computing
	     */
	    BU_ALLOC(ed, struct ve_dist);
	    ed->magic_p = &ved->v1->magic;
	    ed->status = ved->status;
	    ed->v1 = ed->v2 = ved->v1;

	    BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC);
	    BU_LIST_APPEND(&fpi->ve_dh, &ed->l);

	    if (fpi->vu_func &&
		(fpi->hits == NMG_FPI_PERUSE ||
		 (fpi->hits == NMG_FPI_PERGEOM && !found_data))) {
		/* need to cast vu_func pointer for actual use as a function */
		void (*cfp)(struct vertexuse *, point_t, const char*);
		cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func;
		cfp(eu->vu_p, fpi->pt, fpi->priv);
	    }

	    break;
	case 2:	/* within tolerance of endpoint at ved->v2 */
	    ei->nmg_class = NMG_CLASS_AonBshared;
	    /* add an entry for the vertex in the edge list so that
	     * other uses of this vertex will claim the point is within
	     * tolerance without re-computing
	     */
	    BU_ALLOC(ed, struct ve_dist);
	    ed->magic_p = &ved->v2->magic;
	    ed->status = ved->status;
	    ed->v1 = ed->v2 = ved->v2;

	    BU_LIST_MAGIC_SET(&ed->l, NMG_VE_DIST_MAGIC);
	    BU_LIST_APPEND(&fpi->ve_dh, &ed->l);
	    if (fpi->vu_func &&
		(fpi->hits == NMG_FPI_PERUSE ||
		 (fpi->hits == NMG_FPI_PERGEOM && !found_data))) {
		/* need to cast vu_func pointer for actual use as a function */
		void (*cfp)(struct vertexuse *, point_t, const char*);
		cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func;
		cfp(eu->eumate_p->vu_p, fpi->pt, fpi->priv);
	    }
	    break;

	case 3: /* PCA of pt on line is within tolerance of ved->v1 of segment */
	    ei->nmg_class = nmg_class_pt_euvu(fpi->pt, eu, fpi->tol);
	    if (ei->nmg_class == NMG_CLASS_Unknown)
		ei->ved_p->dist = MAX_FASTF;
	    break;
	case 4: /* PCA of pt on line is within tolerance of ved->v2 of segment */
	    next_eu = BU_LIST_PNEXT_CIRC(edgeuse, &eu->l);
	    ei->nmg_class = nmg_class_pt_euvu(fpi->pt, next_eu, fpi->tol);
	    if (ei->nmg_class == NMG_CLASS_Unknown)
		ei->ved_p->dist = MAX_FASTF;
	    break;

	case 5: /* PCA is along length of edge, but point is NOT on edge. */
	    if (nmg_find_eu_left_non_unit(left, eu))
		bu_bomb("can't find left vector\n");
	    /* take dot product of v->pt vector with left to determine
	     * if pt is inside/left of edge
	     */
	    VSUB2(v_to_pt, fpi->pt, eu_pt);
	    if (VDOT(v_to_pt, left) > -SMALL_FASTF)
		ei->nmg_class = NMG_CLASS_AinB;
	    else
		ei->nmg_class = NMG_CLASS_AoutB;
	    break;
	default:
	    bu_log("%s:%d status = %d\n", __FILE__, __LINE__, ved->status);
	    bu_bomb("Why did this happen?");
	    break;
    }


    if (RTG.NMG_debug & DEBUG_PT_FU) {
	bu_log("pt @ dist %g from edge classed %s vs edge\n",
	       ei->ved_p->dist, nmg_class_name(ei->nmg_class));
/* pl_pt_e(fpi, ei); */
    }

    /* now that it's complete, add ei to the edge list */
    for (BU_LIST_FOR(ei_p, edge_info, &edge_list->l)) {
	/* if the distance to this edge is smaller, or
	 * if the distance is the same & the edge is the same
	 * Insert edge_info struct here in list
	 */
	if (ved->dist < ei_p->ved_p->dist
	    || (ZERO(ved->dist - ei_p->ved_p->dist)
		&& ei_p->ved_p->magic_p == ved->magic_p))
	{
	    break;
	}
    }

    BU_LIST_INSERT(&ei_p->l, &ei->l);
    return ei;
}
Exemplo n.º 16
0
/*
 * Open/create a framebuffer object.
 *
 * Usage:
 *	  fb_open [name device [args]]
 */
HIDDEN int
fbo_open_tcl(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
{
    struct fb_obj *fbop;
    FBIO *ifp;
    int width = 512;
    int height = 512;
    register int c;
    struct bu_vls vls;

    if (argc == 1) {
	/* get list of framebuffer objects */
	for (BU_LIST_FOR(fbop, fb_obj, &HeadFBObj.l))
	    Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), " ", (char *)NULL);

	return TCL_OK;
    }

    if (argc < 3) {
	bu_vls_init(&vls);
	bu_vls_printf(&vls, "helplib fb_open");
	Tcl_Eval(interp, bu_vls_addr(&vls));
	bu_vls_free(&vls);
	return TCL_ERROR;
    }

    /* process args */
    bu_optind = 3;
    bu_opterr = 0;
    while ((c = bu_getopt(argc, argv, "w:W:s:S:n:N:")) != EOF)  {
	switch (c) {
	    case 'W':
	    case 'w':
		width = atoi(bu_optarg);
		break;
	    case 'N':
	    case 'n':
		height = atoi(bu_optarg);
		break;
	    case 'S':
	    case 's':
		width = atoi(bu_optarg);
		height = width;
		break;
	    case '?':
	    default:
		Tcl_AppendResult(interp, "fb_open: bad option - ",
				 bu_optarg, (char *)NULL);
		return TCL_ERROR;
	}
    }

    if ((ifp = fb_open(argv[2], width, height)) == FBIO_NULL) {
	Tcl_AppendResult(interp, "fb_open: bad device - ",
			 argv[2], (char *)NULL);
    }

    if (fb_ioinit(ifp) != 0) {
	Tcl_AppendResult(interp, "fb_open: fb_ioinit() failed.", (char *) NULL);
	return TCL_ERROR;
    }

    BU_GETSTRUCT(fbop, fb_obj);
    bu_vls_init(&fbop->fbo_name);
    bu_vls_strcpy(&fbop->fbo_name, argv[1]);
    fbop->fbo_fbs.fbs_fbp = ifp;
    fbop->fbo_fbs.fbs_listener.fbsl_fbsp = &fbop->fbo_fbs;
    fbop->fbo_fbs.fbs_listener.fbsl_fd = -1;
    fbop->fbo_fbs.fbs_listener.fbsl_port = -1;

    /* append to list of fb_obj's */
    BU_LIST_APPEND(&HeadFBObj.l, &fbop->l);

    (void)Tcl_CreateCommand(interp,
			    bu_vls_addr(&fbop->fbo_name),
			    (Tcl_CmdProc *)fbo_cmd,
			    (ClientData)fbop,
			    fbo_deleteProc);

    /* Return new function name as result */
    Tcl_ResetResult(interp);
    Tcl_AppendResult(interp, bu_vls_addr(&fbop->fbo_name), (char *)NULL);
    return TCL_OK;
}
Exemplo n.º 17
0
int
ged_shells(struct ged *gedp, int argc, const char *argv[])
{
    struct directory *old_dp, *new_dp;
    struct rt_db_internal old_intern, new_intern;
    struct model *m_tmp, *m;
    struct nmgregion *r_tmp, *r;
    struct shell *s_tmp, *s;
    int shell_count=0;
    struct bu_vls shell_name = BU_VLS_INIT_ZERO;
    long **trans_tbl;
    static const char *usage = "nmg_model";

    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 != 2) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    if ((old_dp = db_lookup(gedp->ged_wdbp->dbip,  argv[1], LOOKUP_NOISY)) == RT_DIR_NULL)
	return GED_ERROR;

    if (rt_db_get_internal(&old_intern, old_dp, gedp->ged_wdbp->dbip, bn_mat_identity, &rt_uniresource) < 0) {
	bu_vls_printf(gedp->ged_result_str, "rt_db_get_internal() error\n");
	return GED_ERROR;
    }

    if (old_intern.idb_type != ID_NMG) {
	bu_vls_printf(gedp->ged_result_str, "Object is not an NMG!!!\n");
	return GED_ERROR;
    }

    m = (struct model *)old_intern.idb_ptr;
    NMG_CK_MODEL(m);

    for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) {
	for (BU_LIST_FOR(s, shell, &r->s_hd)) {
	    s_tmp = nmg_dup_shell(s, &trans_tbl, &gedp->ged_wdbp->wdb_tol);
	    bu_free((void *)trans_tbl, "trans_tbl");

	    m_tmp = nmg_mmr();
	    r_tmp = BU_LIST_FIRST(nmgregion, &m_tmp->r_hd);

	    BU_LIST_DEQUEUE(&s_tmp->l);
	    BU_LIST_APPEND(&r_tmp->s_hd, &s_tmp->l);
	    s_tmp->r_p = r_tmp;
	    nmg_m_reindex(m_tmp, 0);
	    nmg_m_reindex(m, 0);

	    bu_vls_printf(&shell_name, "shell.%d", shell_count);
	    while (db_lookup(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), 0) != RT_DIR_NULL) {
		bu_vls_trunc(&shell_name, 0);
		shell_count++;
		bu_vls_printf(&shell_name, "shell.%d", shell_count);
	    }

	    /* Export NMG as a new solid */
	    RT_DB_INTERNAL_INIT(&new_intern);
	    new_intern.idb_major_type = DB5_MAJORTYPE_BRLCAD;
	    new_intern.idb_type = ID_NMG;
	    new_intern.idb_meth = &OBJ[ID_NMG];
	    new_intern.idb_ptr = (void *)m_tmp;

	    new_dp=db_diradd(gedp->ged_wdbp->dbip, bu_vls_addr(&shell_name), RT_DIR_PHONY_ADDR, 0, RT_DIR_SOLID, (void *)&new_intern.idb_type);
	    if (new_dp == RT_DIR_NULL) {
		bu_vls_printf(gedp->ged_result_str, "An error has occurred while adding a new object to the database.\n");
		return GED_ERROR;
	    }

	    /* make sure the geometry/bounding boxes are up to date */
	    nmg_rebound(m_tmp, &gedp->ged_wdbp->wdb_tol);

	    if (rt_db_put_internal(new_dp, gedp->ged_wdbp->dbip, &new_intern, &rt_uniresource) < 0) {
		/* Free memory */
		nmg_km(m_tmp);
		bu_vls_printf(gedp->ged_result_str, "rt_db_put_internal() failure\n");
		return GED_ERROR;
	    }
	    /* Internal representation has been freed by rt_db_put_internal */
	    new_intern.idb_ptr = (void *)NULL;
	}
    }
    bu_vls_free(&shell_name);

    return GED_OK;
}
void
Do_subfigs()
{
    int i, j;
    int entity_type;
    struct wmember head1;
    struct wmember *wmem;

    if (RT_G_DEBUG & DEBUG_MEM_FULL)
	bu_mem_barriercheck();

    BU_LIST_INIT(&head1.l);

    for (i = 0; i < totentities; i++) {
	int subfigdef_de;
	int subfigdef_index;
	int no_of_members;
	int *members;
	char *name = NULL;
	struct wmember head2;
	double mat_scale[3];
	int non_unit;

	if (dir[i]->type != 408)
	    continue;

	if (RT_G_DEBUG & DEBUG_MEM_FULL)
	    bu_mem_barriercheck();

	if (dir[i]->param <= pstart) {
	    bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		   dir[i]->direct, dir[i]->name);
	    continue;
	}

	Readrec(dir[i]->param);
	Readint(&entity_type, "");
	if (entity_type != 408) {
	    bu_log("Expected Singular Subfigure Instance Entity, found %s\n",
		   iges_type(entity_type));
	    continue;
	}

	Readint(&subfigdef_de, "");
	subfigdef_index = (subfigdef_de - 1)/2;
	if (subfigdef_index >= totentities) {
	    bu_log("Singular Subfigure Instance Entity gives Subfigure Definition");
	    bu_log("\tEntity DE of %d, largest DE in file is %d\n",
		   subfigdef_de, (totentities * 2) - 1);
	    continue;
	}
	if (dir[subfigdef_index]->type != 308) {
	    bu_log("Expected Subfigure Definition Entity, found %s\n",
		   iges_type(dir[subfigdef_index]->type));
	    continue;
	}

	if (dir[subfigdef_index]->param <= pstart) {
	    bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		   dir[subfigdef_index]->direct, dir[subfigdef_index]->name);
	    continue;
	}
	Readrec(dir[subfigdef_index]->param);
	Readint(&entity_type, "");
	if (entity_type != 308) {
	    bu_log("Expected Subfigure Definition Entity, found %s\n",
		   iges_type(entity_type));
	    continue;
	}

	Readint(&j, "");	/* ignore depth */
	Readstrg("");		/* ignore subfigure name */

	wmem = mk_addmember(dir[subfigdef_index]->name, &head1.l, NULL, WMOP_UNION);
	non_unit = 0;
	for (j = 0; j < 3; j++) {
	    double mag_sq;

	    mat_scale[j] = 1.0;
	    mag_sq = MAGSQ(&(*dir[i]->rot)[j*4]);

	    /* FIXME: arbitrary undefined tolerance */
	    if (!NEAR_EQUAL(mag_sq, 1.0, 100.0*SQRT_SMALL_FASTF)) {
		mat_scale[j] = 1.0/sqrt(mag_sq);
		non_unit = 1;
	    }
	}

	if (non_unit) {
	    bu_log("Illegal transformation matrix in %s for member %s\n",
		   curr_file->obj_name, wmem->wm_name);
	    bu_log(" row vector magnitudes are %g, %g, and %g\n",
		   1.0/mat_scale[0], 1.0/mat_scale[1], 1.0/mat_scale[2]);
	    bn_mat_print("", *dir[i]->rot);
	    for (j = 0; j < 11; j++) {
		if ((j+1)%4 == 0)
		    continue;
		(*dir[i]->rot)[j] *= mat_scale[0];
	    }
	    bn_mat_print("After scaling:", *dir[i]->rot);

	}
	memcpy(wmem->wm_mat, *dir[i]->rot, sizeof(mat_t));

	Readint(&no_of_members, "");	/* get number of members */
	members = (int *)bu_calloc(no_of_members, sizeof(int), "Do_subfigs: members");
	for (j = 0; j < no_of_members; j++)
	    Readint(&members[j], "");

	BU_LIST_INIT(&head2.l);
	for (j = 0; j < no_of_members; j++) {
	    int idx;

	    idx = (members[j] - 1)/2;

	    if (idx >= totentities) {
		bu_log("Subfigure Definition Entity gives Member Entity");
		bu_log("\tDE of %d, largest DE in file is %d\n",
		       members[j], (totentities * 2) - 1);
		continue;
	    }
	    if (dir[idx]->param <= pstart) {
		bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
		       dir[idx]->direct, dir[idx]->name);
		continue;
	    }

	    if (dir[idx]->type == 416) {
		struct file_list *list_ptr;
		char *file_name;
		int found = 0;

		/* external reference */

		Readrec(dir[idx]->param);
		Readint(&entity_type, "");

		if (entity_type != 416) {
		    bu_log("Expected External reference Entity, found %s\n",
			   iges_type(entity_type));
		    continue;
		}

		if (dir[idx]->form != 1) {
		    bu_log("External Reference Entity of form #%d found\n",
			   dir[idx]->form);
		    bu_log("\tOnly form #1 is currently handled\n");
		    continue;
		}

		Readname(&file_name, "");

		/* Check if this external reference is already on the list */
		for (BU_LIST_FOR(list_ptr, file_list, &iges_list.l)) {
		    if (BU_STR_EQUAL(file_name, list_ptr->file_name)) {
			found = 1;
			name = list_ptr->obj_name;
			break;
		    }
		}

		if (!found) {
		    /* Need to add this one to the list */
		    BU_ALLOC(list_ptr, struct file_list);

		    list_ptr->file_name = file_name;
		    if (no_of_members == 1)
			bu_strlcpy(list_ptr->obj_name, dir[subfigdef_index]->name, NAMESIZE+1);
		    else {
			bu_strlcpy(list_ptr->obj_name, "subfig", NAMESIZE+1);
			(void) Make_unique_brl_name(list_ptr->obj_name);
		    }


		    BU_LIST_APPEND(&curr_file->l, &list_ptr->l);

		    name = list_ptr->obj_name;
		} else
		    bu_free((char *)file_name, "Do_subfigs: file_name");

	    } else
		name = dir[idx]->name;

	    if (no_of_members > 1) {
		wmem = mk_addmember(name, &head2.l, NULL, WMOP_UNION);
		memcpy(wmem->wm_mat, dir[idx]->rot, sizeof(mat_t));
	    }
	}

	if (no_of_members > 1)
	    (void)mk_lcomb(fdout, dir[subfigdef_index]->name, &head2, 0,
			   (char *)NULL, (char *)NULL, (unsigned char *)NULL, 0);
    }
Exemplo n.º 19
0
struct rt_nurb_uv_hit *
rt_nurb_intersect(const struct face_g_snurb *srf, fastf_t *plane1, fastf_t *plane2, double uv_tol, struct resource *res, struct bu_list *plist)
{
    struct rt_nurb_uv_hit * h;
    struct face_g_snurb * psrf,
	* osrf;
    int dir,
	sub;

    point_t vmin,
	vmax;
    fastf_t u[2],
	v[2];
    struct bu_list rni_plist;

    NMG_CK_SNURB(srf);

    h = (struct rt_nurb_uv_hit *) 0;
    if (plist == NULL) {
	plist = &rni_plist;
	BU_LIST_INIT(plist);
    }

    /* project the surface to a 2 dimensional problem */
    /* NOTE that this gives a single snurb back, NOT a list */
    psrf = rt_nurb_project_srf(srf, plane2, plane1, res);
    psrf->dir = 1;
    BU_LIST_APPEND(plist, &psrf->l);

    if (RT_G_DEBUG & DEBUG_SPLINE)
	rt_nurb_s_print("srf", psrf);

    /* This list starts out with only a single snurb, but more may be
     * added on as work progresses.
     */
    while (BU_LIST_WHILE(psrf, face_g_snurb, plist)) {
	int flat;

	BU_LIST_DEQUEUE(&psrf->l);
	NMG_CK_SNURB(psrf);
	sub = 0;
	flat = 0;
	dir = psrf->dir;

	while (!flat) {
	    fastf_t smin = 0.0, smax = 0.0;

	    sub++;
	    dir = (dir == 0)?1:0;	/* change direction */

	    if (RT_G_DEBUG & DEBUG_SPLINE)
		rt_nurb_s_print("psrf", psrf);

	    rt_nurb_pbound(psrf, vmin, vmax);

	    /* Check for origin to be included in the bounding box */
	    if (!(vmin[0] <= 0.0 && vmin[1] <= 0.0 &&
		  vmax[0] >= 0.0 && vmax[1] >= 0.0)) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("this srf doesn't include the origin\n");
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }

	    rt_nurb_clip_srf(psrf, dir, &smin, &smax);

	    if ((smax - smin) > .8) {
		struct rt_nurb_uv_hit *hp;

		/* Split surf, requeue both sub-surfs at head */
		/* New surfs will have same dir as arg, here */
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("splitting this surface\n");
		rt_nurb_s_split(plist, psrf, dir, res);
		rt_nurb_free_snurb(psrf, res);

		hp = rt_nurb_intersect(srf, plane1, plane2, uv_tol, res, plist);
		return hp;
	    }
	    if (smin > 1.0 || smax < 0.0) {
		if (RT_G_DEBUG & DEBUG_SPLINE)
		    bu_log("eliminating this surface (smin=%g, smax=%g)\n", smin, smax);
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
		continue;
	    }
	    if (dir == RT_NURB_SPLIT_ROW) {
		smin = (1.0 - smin) * psrf->u.knots[0] +
		    smin * psrf->u.knots[
			psrf->u.k_size -1];
		smax = (1.0 - smax) * psrf->u.knots[0] +
		    smax * psrf->u.knots[
			psrf->u.k_size -1];
	    } else {
		smin = (1.0 - smin) * psrf->v.knots[0] +
		    smin * psrf->v.knots[
			psrf->v.k_size -1];
		smax = (1.0 - smax) * psrf->v.knots[0] +
		    smax * psrf->v.knots[
			psrf->v.k_size -1];
	    }

	    osrf = psrf;
	    psrf = (struct face_g_snurb *) rt_nurb_region_from_srf(
		osrf, dir, smin, smax, res);

	    psrf->dir = dir;
	    rt_nurb_free_snurb(osrf, res);

	    if (RT_G_DEBUG & DEBUG_SPLINE) {
		bu_log("After call to rt_nurb_region_from_srf() (smin=%g, smax=%g)\n", smin, smax);
		rt_nurb_s_print("psrf", psrf);
	    }

	    u[0] = psrf->u.knots[0];
	    u[1] = psrf->u.knots[psrf->u.k_size -1];

	    v[0] = psrf->v.knots[0];
	    v[1] = psrf->v.knots[psrf->v.k_size -1];

	    if ((u[1] - u[0]) < uv_tol && (v[1] - v[0]) < uv_tol) {
		struct rt_nurb_uv_hit * hit;

		if (RT_G_DEBUG & DEBUG_SPLINE) {
		    fastf_t p1[4], p2[4];
		    int coords;
		    vect_t diff;

		    coords = RT_NURB_EXTRACT_COORDS(srf->pt_type);
		    rt_nurb_s_eval(srf, u[0], v[0], p1);
		    rt_nurb_s_eval(srf, u[1], v[1], p2);

		    if (RT_NURB_IS_PT_RATIONAL(srf->pt_type)) {
			fastf_t inv_w;

			inv_w = 1.0 / p1[coords-1];
			VSCALE(p1, p1, inv_w);

			inv_w = 1.0 / p2[coords-1];
			VSCALE(p2, p2, inv_w);
		    }

		    VSUB2(diff, p1, p2);
		    bu_log("Precision of hit point = %g (%f %f %f) <-> (%f %f %f)\n",
			   MAGNITUDE(diff), V3ARGS(p1), V3ARGS(p2));
		}

		hit = (struct rt_nurb_uv_hit *) bu_malloc(
		    sizeof(struct rt_nurb_uv_hit),  "hit");

		hit->next = (struct rt_nurb_uv_hit *)0;
		hit->sub = sub;
		hit->u = (u[0] + u[1])/2.0;
		hit->v = (v[0] + v[1])/2.0;

		if (h == (struct rt_nurb_uv_hit *)0)
		    h = hit;
		else {
		    hit->next = h;
		    h = hit;
		}
		flat = 1;
		rt_nurb_free_snurb(psrf, res);
	    }
	    if ((u[1] - u[0]) > (v[1] - v[0]))
		dir = 1;
	    else dir = 0;
	}
    }

    return (struct rt_nurb_uv_hit *)h;
}
Exemplo n.º 20
0
/**
 * Algorithm
 *
 * Given a parametric direction (u or v) look at the direction knot
 * vector and insert a multiple knot of parametric direction surface
 * order. This is somewhat different than rt_nurb_split in that the
 * surface is give a parametric value at which to split the surface.
 * rt_nurb_kvmult does the right thing in inserting a multiple knot
 * with the correct amount. Separate the surface and return the two
 * resulting surface.
 */
struct face_g_snurb *
rt_nurb_s_xsplit(struct face_g_snurb *srf, fastf_t param, int dir)
{
    struct knot_vector new_kv;
    struct oslo_mat * oslo;
    int i;
    int k_index;
    struct face_g_snurb * srf1, * srf2;

    NMG_CK_SNURB(srf);

    if (dir == RT_NURB_SPLIT_ROW) {
	rt_nurb_kvmult(&new_kv, &srf->u, srf->order[0], param, (struct resource *)NULL);

	k_index = srf->order[0];

	oslo = (struct oslo_mat *)
	    rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_ROW], &srf->u, &new_kv, (struct resource *)NULL);

	GET_SNURB(srf1);
	srf1->order[0]  = srf->order[0];
	srf1->order[1]  = srf->order[1];
	srf1->dir = RT_NURB_SPLIT_ROW;
	rt_nurb_kvextract(&srf1->u, &new_kv, 0, k_index + srf1->order[0], (struct resource *)NULL);
	rt_nurb_kvcopy(&srf1->v, &srf->v, (struct resource *)NULL);

	srf1->pt_type = srf->pt_type;
	srf1->s_size[0] = srf1->v.k_size -
	    srf1->order[1];
	srf1->s_size[1] = srf1->u.k_size -
	    srf1->order[0];

	srf1->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
		      srf1->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf1->pt_type),
		      "rt_nurb_s_xsplit: srf1 row mesh control points");

	GET_SNURB(srf2);
	srf2->order[0]  = srf->order[0];
	srf2->order[1]  = srf->order[1];
	srf2->dir = RT_NURB_SPLIT_ROW;
	rt_nurb_kvextract(&srf2->u, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
	rt_nurb_kvcopy(&srf2->v, &srf->v, (struct resource *)NULL);

	srf2->pt_type = srf->pt_type;
	srf2->s_size[0] = srf2->v.k_size -
	    srf2->order[1];
	srf2->s_size[1] = srf2->u.k_size -
	    srf2->order[0];

	srf2->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
		      srf2->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf2->pt_type),
		      "rt_nurb_s_xsplit: srf2 row mesh control points");

	for (i = 0; i < srf->s_size[0]; i++) {
	    fastf_t * old_mesh_ptr;
	    fastf_t * new_mesh_ptr;

	    old_mesh_ptr = &srf->ctl_points[
		i * srf->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf->pt_type)];
	    new_mesh_ptr = &srf1->ctl_points[
		i * srf1->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
			     0, k_index, srf1->pt_type);
	    new_mesh_ptr = &srf2->ctl_points[
		i * srf2->s_size[1] *
		RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
			     k_index, new_kv.k_size - srf2->order[0],
			     srf2->pt_type);
	}
    } else {
	rt_nurb_kvmult(&new_kv, &srf->v, srf->order[RT_NURB_SPLIT_COL], param, (struct resource *)NULL);

	k_index = srf->order[1];

	oslo = (struct oslo_mat *)
	    rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_COL], &srf->v, &new_kv, (struct resource *)NULL);

	GET_SNURB(srf1);
	srf1->order[0]  = srf->order[0];
	srf1->order[1]  = srf->order[1];
	srf1->dir = RT_NURB_SPLIT_COL;
	rt_nurb_kvextract(&srf1->v, &new_kv, 0, k_index + srf1->order[RT_NURB_SPLIT_COL], (struct resource *)NULL);
	rt_nurb_kvcopy(&srf1->u, &srf->u, (struct resource *)NULL);

	srf1->pt_type = srf->pt_type;
	srf1->s_size[0] = srf1->v.k_size -
	    srf1->order[1];
	srf1->s_size[1] = srf1->u.k_size -
	    srf1->order[0];

	srf1->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
		      srf1->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf1->pt_type),
		      "rt_nurb_split: srf1 row mesh control points");

	GET_SNURB(srf2);
	srf2->order[0]  = srf->order[0];
	srf2->order[1]  = srf->order[1];
	srf2->dir = RT_NURB_SPLIT_COL;
	rt_nurb_kvextract(&srf2->v, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
	rt_nurb_kvcopy(&srf2->u, &srf->u, (struct resource *)NULL);

	srf2->pt_type = srf->pt_type;
	srf2->s_size[0] = srf2->v.k_size -
	    srf2->order[1];
	srf2->s_size[1] = srf2->u.k_size -
	    srf2->order[0];

	srf2->ctl_points = (fastf_t *)
	    bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
		      srf2->s_size[1] *
		      RT_NURB_EXTRACT_COORDS(srf2->pt_type),
		      "rt_nurb_s_xsplit: srf2 row mesh control points");

	for (i = 0; i < srf->s_size[1]; i++) {
	    fastf_t * old_mesh_ptr;
	    fastf_t * new_mesh_ptr;

	    old_mesh_ptr = &srf->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf->pt_type)];
	    new_mesh_ptr = &srf1->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     srf->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     srf1->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
			     0, k_index, srf1->pt_type);
	    new_mesh_ptr = &srf2->ctl_points[
		i * RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
	    rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
			     srf->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf->pt_type),
			     srf2->s_size[1] *
			     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
			     k_index, new_kv.k_size - srf2->order[1],
			     srf2->pt_type);
	}
    }

    BU_LIST_APPEND(&srf1->l, &srf2->l);

    bu_free((char *) new_kv.knots, "rt_nurb_s_xsplit: new_kv.knots");

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    return srf1;
}
Exemplo n.º 21
0
struct bu_mapped_file *
bu_open_mapped_file(const char *name, const char *appl)
/* file name */
/* non-null only when app. will use 'apbuf' */
{
    struct bu_mapped_file *mp = (struct bu_mapped_file *)NULL;
    char *real_path = bu_realpath(name, NULL);
#ifdef HAVE_SYS_STAT_H
    struct stat sb;
    int fd = -1;	/* unix file descriptor */
    int readval;
    ssize_t bytes_to_go, nbytes;
#else
    FILE *fp = (FILE *)NULL;	/* stdio file pointer */
#endif
    int ret;

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_log("bu_open_mapped_file(%s(canonical path - %s), %s)\n", name, real_path, appl?appl:"(NIL)");

    /* See if file has already been mapped, and can be shared */
    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
    if (!BU_LIST_IS_INITIALIZED(&bu_mapped_file_list)) {
	BU_LIST_INIT(&bu_mapped_file_list);
    }

    for (BU_LIST_FOR(mp, bu_mapped_file, &bu_mapped_file_list)) {
	BU_CK_MAPPED_FILE(mp);

	/* find a match */

	if (!BU_STR_EQUAL(real_path, mp->name))
	    continue;
	if (appl && !BU_STR_EQUAL(appl, mp->appl))
	    continue;

	/* found a match */

	/* if mapped file still exists, verify size and modtime */
	if (!mp->dont_restat) {

	    bu_semaphore_acquire(BU_SEM_SYSCALL);
	    fd = open(real_path, O_RDONLY | O_BINARY);
	    bu_semaphore_release(BU_SEM_SYSCALL);

	    /* If file didn't vanish from disk, make sure it's the same file */
	    if (fd >= 0) {

#ifdef HAVE_SYS_STAT_H
		bu_semaphore_acquire(BU_SEM_SYSCALL);
		ret = fstat(fd, &sb);
		bu_semaphore_release(BU_SEM_SYSCALL);

		if (ret < 0) {
		    /* odd, open worked but fstat failed.  assume it
		     * vanished from disk and the mapped copy is still
		     * OK.
		     */

		    bu_semaphore_acquire(BU_SEM_SYSCALL);
		    (void)close(fd);
		    bu_semaphore_release(BU_SEM_SYSCALL);
		    fd = -1;
		}
		if ((size_t)sb.st_size != mp->buflen) {
		    bu_log("bu_open_mapped_file(%s) WARNING: File size changed from %ld to %ld, opening new version.\n", real_path, mp->buflen, sb.st_size);
		    /* mp doesn't reflect the file any longer.  Invalidate. */
		    mp->appl = bu_strdup("__STALE__");
		    /* Can't invalidate old copy, it may still be in use. */
		    break;
		}
		if (sb.st_mtime != mp->modtime) {
		    bu_log("bu_open_mapped_file(%s) WARNING: File modified since last mapped, opening new version.\n", real_path);
		    /* mp doesn't reflect the file any longer.  Invalidate. */
		    mp->appl = bu_strdup("__STALE__");
		    /* Can't invalidate old copy, it may still be in use. */
		    break;
		}
		/* To be completely safe, should check st_dev and st_inum */
#endif
	    }

	    /* It is safe to reuse mp */
	    mp->uses++;

	    bu_semaphore_release(BU_SEM_MAPPEDFILE);
	    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
		bu_pr_mapped_file("open_reused", mp);

	    return mp;
	}

	/* It is safe to reuse mp */
	mp->uses++;
	return mp;

    }
    /* done iterating over mapped file list */
    bu_semaphore_release(BU_SEM_MAPPEDFILE);

    /* necessary in case we take a 'fail' path before BU_ALLOC() */
    mp = NULL;

    /* File is not yet mapped or has changed, open file read only if
     * we didn't find it earlier.
     */
#ifdef HAVE_SYS_STAT_H
    if (fd < 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	fd = open(real_path, O_RDONLY | O_BINARY);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    if (UNLIKELY(fd < 0)) {
	if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	    perror(real_path);
	goto fail;
    }

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    ret = fstat(fd, &sb);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(ret < 0)) {
	perror(real_path);
	goto fail;
    }

    if (UNLIKELY(sb.st_size == 0)) {
	bu_log("bu_open_mapped_file(%s) 0-length file\n", real_path);
	goto fail;
    }
#endif /* HAVE_SYS_STAT_H */

    /* Optimistically assume that things will proceed OK */
    BU_ALLOC(mp, struct bu_mapped_file);
    mp->name = bu_strdup(real_path);
    if (appl) mp->appl = bu_strdup(appl);

#ifdef HAVE_SYS_STAT_H
    mp->buflen = sb.st_size;
    mp->modtime = sb.st_mtime;
#  ifdef HAVE_SYS_MMAN_H

    /* Attempt to access as memory-mapped file */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    mp->buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(mp->buf == MAP_FAILED))
	perror(real_path);

    if (mp->buf != MAP_FAILED) {
	/* OK, its memory mapped in! */
	mp->is_mapped = 1;
	/* It's safe to close the fd now, the manuals say */
    } else
#  endif /* HAVE_SYS_MMAN_H */
    {
	/* Allocate a local zero'd buffer, and slurp it in always
	 * leaving space for a trailing zero.
	 */
	mp->buf = bu_calloc(1, sb.st_size+1, real_path);

	nbytes = 0;
	bytes_to_go = sb.st_size;
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	while (nbytes < sb.st_size) {
	    readval = read(fd, ((char *)(mp->buf)) + nbytes, ((bytes_to_go > INT_MAX) ? (INT_MAX) : (bytes_to_go)));
	    if (UNLIKELY(readval < 0)) {
		bu_semaphore_release(BU_SEM_SYSCALL);
		perror(real_path);
		bu_free(mp->buf, real_path);
		goto fail;
	    } else {
		nbytes += readval;
		bytes_to_go -= readval;
	    }
	}
	bu_semaphore_release(BU_SEM_SYSCALL);

	if (UNLIKELY(nbytes != sb.st_size)) {
	    perror(real_path);
	    bu_free(mp->buf, real_path);
	    goto fail;
	}
    }

#else /* !HAVE_SYS_STAT_H */

    /* Read it in with stdio, with no clue how big it is */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    fp = fopen(real_path, "rb");
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(fp == NULL)) {
	perror(real_path);
	goto fail;
    }
    /* Read it once to see how large it is */
    {
	char buf[32768] = {0};
	int got;
	mp->buflen = 0;

	bu_semaphore_acquire(BU_SEM_SYSCALL);
	while ((got = fread(buf, 1, sizeof(buf), fp)) > 0)
	    mp->buflen += got;
	rewind(fp);
	bu_semaphore_release(BU_SEM_SYSCALL);

    }
    /* Allocate the necessary buffer */
    mp->buf = bu_calloc(1, mp->buflen+1, real_path);

    /* Read it again into the buffer */
    bu_semaphore_acquire(BU_SEM_SYSCALL);
    ret = fread(mp->buf, mp->buflen, 1, fp);
    bu_semaphore_release(BU_SEM_SYSCALL);

    if (UNLIKELY(ret != 1)) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	perror("fread");
	fclose(fp);
	bu_semaphore_release(BU_SEM_SYSCALL);

	bu_log("bu_open_mapped_file() 2nd fread failed? len=%d\n", mp->buflen);
	bu_free(mp->buf, "non-unix fread buf");
	goto fail;
    }

    bu_semaphore_acquire(BU_SEM_SYSCALL);
    fclose(fp);
    bu_semaphore_release(BU_SEM_SYSCALL);
#endif

    if (fd >= 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	(void)close(fd);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    mp->uses = 1;
    mp->l.magic = BU_MAPPED_FILE_MAGIC;

    bu_semaphore_acquire(BU_SEM_MAPPEDFILE);
    BU_LIST_APPEND(&bu_mapped_file_list, &mp->l);
    bu_semaphore_release(BU_SEM_MAPPEDFILE);

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE)) {
	bu_pr_mapped_file("1st_open", mp);
    }
    if (real_path) {
	bu_free(real_path, "real_path alloc from bu_realpath");
    }
    return mp;

fail:
    if (fd >= 0) {
	bu_semaphore_acquire(BU_SEM_SYSCALL);
	(void)close(fd);
	bu_semaphore_release(BU_SEM_SYSCALL);
    }

    if (mp) {
	bu_free(mp->name, "mp->name");
	if (mp->appl) bu_free(mp->appl, "mp->appl");
	/* Don't free mp->buf here, it might not be bu_malloced but mmaped */
	bu_free(mp, "mp from bu_open_mapped_file fail");
    }

    if (UNLIKELY(bu_debug&BU_DEBUG_MAPPED_FILE))
	bu_log("bu_open_mapped_file(%s, %s) can't open file\n",
		real_path, appl ? appl: "(NIL)");

    if (real_path) {
	bu_free(real_path, "real_path alloc from bu_realpath");
    }

    return (struct bu_mapped_file *)NULL;
}
Exemplo n.º 22
0
int
_ged_run_rtwizard(struct ged *gedp)
{
    int i;
    FILE *fp_in;
#ifndef _WIN32
    int pipe_in[2];
    int pipe_err[2];
#else
    HANDLE pipe_in[2], pipe_inDup;
    HANDLE pipe_err[2], pipe_errDup;
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    SECURITY_ATTRIBUTES sa = {0};
    struct bu_vls line = BU_VLS_INIT_ZERO;
#endif
    struct ged_run_rt *run_rtp;
    struct _ged_rt_client_data *drcdp;
#ifndef _WIN32
    int pid;
    int ret;

    ret = pipe(pipe_in);
    if (ret < 0)
	perror("pipe");
    ret = pipe(pipe_err);
    if (ret < 0)
	perror("pipe");

    if ((pid = fork()) == 0) {
	/* make this a process group leader */
	setpgid(0, 0);

	/* Redirect stdin and stderr */
	(void)close(0);
	ret = dup(pipe_in[0]);
	if (ret < 0)
	    perror("dup");
	(void)close(2);
	ret = dup(pipe_err[1]);
	if (ret < 0)
	    perror("dup");

	/* close pipes */
	(void)close(pipe_in[0]);
	(void)close(pipe_in[1]);
	(void)close(pipe_err[0]);
	(void)close(pipe_err[1]);

	for (i = 3; i < 20; i++)
	    (void)close(i);

	(void)execvp(gedp->ged_gdp->gd_rt_cmd[0], gedp->ged_gdp->gd_rt_cmd);
	perror(gedp->ged_gdp->gd_rt_cmd[0]);
	exit(16);
    }

    /* As parent, send view information down pipe */
    (void)close(pipe_in[0]);
    fp_in = fdopen(pipe_in[1], "w");

    (void)close(pipe_err[1]);

    (void)fclose(fp_in);

    /* must be BU_GET() to match release in _ged_rt_output_handler */
    BU_GET(run_rtp, struct ged_run_rt);
    BU_LIST_INIT(&run_rtp->l);
    BU_LIST_APPEND(&gedp->ged_gdp->gd_headRunRt.l, &run_rtp->l);

    run_rtp->fd = pipe_err[0];
    run_rtp->pid = pid;

    /* must be BU_GET() to match release in _ged_rt_output_handler */
    BU_GET(drcdp, struct _ged_rt_client_data);
    drcdp->gedp = gedp;
    drcdp->rrtp = run_rtp;

    Tcl_CreateFileHandler(run_rtp->fd,
			  TCL_READABLE,
			  _ged_rt_output_handler,
			  (ClientData)drcdp);

    return 0;

#else
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    /* Create a pipe for the child process's STDOUT. */
    CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0);

    /* Create noninheritable read handle and close the inheritable read handle. */
    DuplicateHandle(GetCurrentProcess(), pipe_err[0],
		    GetCurrentProcess(),  &pipe_errDup ,
		    0,  FALSE,
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_err[0]);

    /* Create a pipe for the child process's STDIN. */
    CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0);

    /* Duplicate the write handle to the pipe so it is not inherited. */
    DuplicateHandle(GetCurrentProcess(), pipe_in[1],
		    GetCurrentProcess(), &pipe_inDup,
		    0, FALSE,                  /* not inherited */
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_in[1]);


    si.cb = sizeof(STARTUPINFO);
    si.lpReserved = NULL;
    si.lpReserved2 = NULL;
    si.cbReserved2 = 0;
    si.lpDesktop = NULL;
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdInput   = pipe_in[0];
    si.hStdOutput  = pipe_err[1];
    si.hStdError   = pipe_err[1];

    for (i = 0; i < gedp->ged_gdp->gd_rt_cmd_len; i++) {
	bu_vls_printf(&line, "\"%s\" ", gedp->ged_gdp->gd_rt_cmd[i]);
    }

    CreateProcess(NULL, bu_vls_addr(&line), NULL, NULL, TRUE,
		  DETACHED_PROCESS, NULL, NULL,
		  &si, &pi);
    bu_vls_free(&line);

    CloseHandle(pipe_in[0]);
    CloseHandle(pipe_err[1]);

    /* As parent, send view information down pipe */
    fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb");

    (void)fclose(fp_in);

    /* must be BU_GET() to match release in _ged_rt_output_handler */
    BU_GET(run_rtp, struct ged_run_rt);
    BU_LIST_INIT(&run_rtp->l);
    BU_LIST_APPEND(&gedp->ged_gdp->gd_headRunRt.l, &run_rtp->l);

    run_rtp->fd = pipe_errDup;
    run_rtp->hProcess = pi.hProcess;
    run_rtp->pid = pi.dwProcessId;
    run_rtp->aborted=0;
    run_rtp->chan = Tcl_MakeFileChannel(run_rtp->fd, TCL_READABLE);

    /* must be BU_GET() to match release in _ged_rt_output_handler */
    BU_GET(drcdp, struct _ged_rt_client_data);
    drcdp->gedp = gedp;
    drcdp->rrtp = run_rtp;

    Tcl_CreateChannelHandler(run_rtp->chan,
			     TCL_READABLE,
			     _ged_rt_output_handler,
			     (ClientData)drcdp);

    return 0;
#endif
}
Exemplo n.º 23
0
/*
 * F _ N I R T
 *
 * Invoke nirt with the current view & stuff
 */
int
dgo_nirt_cmd(struct dg_obj *dgop,
	     struct view_obj *vop,
	     int argc,
	     const char **argv)
{
    const char **vp;
    FILE *fp_in;
    FILE *fp_out, *fp_err;
#ifndef _WIN32
    int ret;
    size_t sret;
    int pid, rpid;
    int retcode;
    int pipe_in[2];
    int pipe_out[2];
    int pipe_err[2];
#else
    HANDLE pipe_in[2], pipe_inDup;
    HANDLE pipe_out[2], pipe_outDup;
    HANDLE pipe_err[2], pipe_errDup;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    char name[1024];
    char line1[2048];
    int rem = 2048;
#endif
    int use_input_orig = 0;
    vect_t center_model;
    vect_t dir;
    vect_t cml;
    int i;
    struct solid *sp;
    char line[RT_MAXLINE];
    char *val;
    struct bu_vls vls = BU_VLS_INIT_ZERO;
    struct bu_vls o_vls = BU_VLS_INIT_ZERO;
    struct bu_vls p_vls = BU_VLS_INIT_ZERO;
    struct bu_vls t_vls = BU_VLS_INIT_ZERO;
    struct bn_vlblock *vbp;
    struct dg_qray_dataList *ndlp;
    struct dg_qray_dataList HeadQRayData;
    int args;

    args = argc + 20 + 2 + dgo_count_tops((struct solid *)&dgop->dgo_headSolid);
    dgop->dgo_rt_cmd = (char **)bu_calloc(args, sizeof(char *), "alloc dgo_rt_cmd");

    vp = (const char **)&dgop->dgo_rt_cmd[0];
    *vp++ = "nirt";

    /* swipe x, y, z off the end if present */
    if (argc > 3) {
	double scan[3];

	if (sscanf(argv[argc-3], "%lf", &scan[X]) == 1 &&
	    sscanf(argv[argc-2], "%lf", &scan[Y]) == 1 &&
	    sscanf(argv[argc-1], "%lf", &scan[Z]) == 1)
	{

	    VMOVE(center_model, scan);
	    use_input_orig = 1;
	    argc -= 3;
	    VSCALE(center_model, center_model, dgop->dgo_wdbp->dbip->dbi_local2base);
	}
    }

    /* Calculate point from which to fire ray */
    if (!use_input_orig) {
	VSET(center_model, -vop->vo_center[MDX],
	     -vop->vo_center[MDY], -vop->vo_center[MDZ]);
    }

    VSCALE(cml, center_model, dgop->dgo_wdbp->dbip->dbi_base2local);
    VMOVEN(dir, vop->vo_rotation + 8, 3);
    VSCALE(dir, dir, -1.0);

    bu_vls_printf(&p_vls, "xyz %lf %lf %lf;",
		  cml[X], cml[Y], cml[Z]);
    bu_vls_printf(&p_vls, "dir %lf %lf %lf; s",
		  dir[X], dir[Y], dir[Z]);

    i = 0;
    if (DG_QRAY_GRAPHICS(dgop)) {

	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_NULL;

	/* first ray ---- returns partitions */
	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_P;

	/* ray start, direction, and 's' command */
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&p_vls);

	/* second ray ---- returns overlaps */
	*vp++ = "-e";
	*vp++ = DG_QRAY_FORMAT_O;

	/* ray start, direction, and 's' command */
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&p_vls);

	if (DG_QRAY_TEXT(dgop)) {
	    char *cp;
	    int count = 0;

	    /* get 'r' format now; prepend its' format string with a newline */
	    val = bu_vls_addr(&dgop->dgo_qray_fmts[0].fmt);

	    /* find first '"' */
	    while (*val != '"' && *val != '\0')
		++val;

	    if (*val == '\0')
		goto done;
	    else
		++val;	    /* skip first '"' */

	    /* find last '"' */
	    cp = (char *)strrchr(val, '"');

	    if (cp != (char *)NULL) /* found it */
		count = cp - val;

	done:
	    if (*val == '\0')
		bu_vls_printf(&o_vls, " fmt r \"\\n\" ");
	    else {
		struct bu_vls tmp = BU_VLS_INIT_ZERO;
		bu_vls_strncpy(&tmp, val, count);
		bu_vls_printf(&o_vls, " fmt r \"\\n%V\" ", &tmp);
		bu_vls_free(&tmp);

		if (count)
		    val += count + 1;
		bu_vls_printf(&o_vls, "%s", val);
	    }

	    i = 1;

	    *vp++ = "-e";
	    *vp++ = bu_vls_addr(&o_vls);
	}
    }

    if (DG_QRAY_TEXT(dgop)) {

	/* load vp with formats for printing */
	for (; dgop->dgo_qray_fmts[i].type != (char)0; ++i)
	    bu_vls_printf(&t_vls, "fmt %c %s; ",
			  dgop->dgo_qray_fmts[i].type,
			  bu_vls_addr(&dgop->dgo_qray_fmts[i].fmt));

	*vp++ = "-e";
	*vp++ = bu_vls_addr(&t_vls);

	/* nirt does not like the trailing ';' */
	bu_vls_trunc(&t_vls, -2);
    }

    /* include nirt script string */
    if (bu_vls_strlen(&dgop->dgo_qray_script)) {
	*vp++ = "-e";
	*vp++ = bu_vls_addr(&dgop->dgo_qray_script);
    }

    *vp++ = "-e";
    *vp++ = bu_vls_addr(&p_vls);

    for (i = 1; i < argc; i++)
	*vp++ = argv[i];
    *vp++ = dgop->dgo_wdbp->dbip->dbi_filename;

    dgop->dgo_rt_cmd_len = (char **)vp - (char **)dgop->dgo_rt_cmd;

    /* Note - dgo_build_tops sets the last vp to (char *)0 */
    dgop->dgo_rt_cmd_len += dgo_build_tops((struct solid *)&dgop->dgo_headSolid,
					   vp,
					   (const char **)&dgop->dgo_rt_cmd[args]);

    if (dgop->dgo_qray_cmd_echo) {
	/* Print out the command we are about to run */
	vp = (const char **)&dgop->dgo_rt_cmd[0];
	while (*vp)
	    Tcl_AppendResult(dgop->interp, *vp++, " ", (char *)NULL);

	Tcl_AppendResult(dgop->interp, "\n", (char *)NULL);
    }

    if (use_input_orig) {
	bu_vls_printf(&vls, "\nFiring from (%lf, %lf, %lf)...\n",
		      center_model[X], center_model[Y], center_model[Z]);
	Tcl_AppendResult(dgop->interp, bu_vls_addr(&vls), (char *)NULL);
	bu_vls_free(&vls);
    } else
	Tcl_AppendResult(dgop->interp, "\nFiring from view center...\n", (char *)NULL);

#ifndef _WIN32
    ret = pipe(pipe_in);
    if (ret < 0)
	perror("pipe");
    ret = pipe(pipe_out);
    if (ret < 0)
	perror("pipe");
    ret = pipe(pipe_err);
    if (ret < 0)
	perror("pipe");
    (void)signal(SIGINT, SIG_IGN);
    if ((pid = fork()) == 0) {
	/* Redirect stdin, stdout, stderr */
	(void)close(0);
	ret = dup(pipe_in[0]);
	if (ret < 0)
	    perror("dup");
	(void)close(1);
	ret = dup(pipe_out[1]);
	if (ret < 0)
	    perror("dup");
	(void)close(2);
	ret = dup(pipe_err[1]);
	if (ret < 0)
	    perror("dup");

	/* close pipes */
	(void)close(pipe_in[0]);
	(void)close(pipe_in[1]);
	(void)close(pipe_out[0]);
	(void)close(pipe_out[1]);
	(void)close(pipe_err[0]);
	(void)close(pipe_err[1]);
	for (i = 3; i < 20; i++)
	    (void)close(i);
	(void)signal(SIGINT, SIG_DFL);
	(void)execvp(dgop->dgo_rt_cmd[0], dgop->dgo_rt_cmd);
	perror (dgop->dgo_rt_cmd[0]);
	exit(16);
    }

    /* use fp_in to feed view info to nirt */
    (void)close(pipe_in[0]);
    fp_in = fdopen(pipe_in[1], "w");

    /* use fp_out to read back the result */
    (void)close(pipe_out[1]);
    fp_out = fdopen(pipe_out[0], "r");

    /* use fp_err to read any error messages */
    (void)close(pipe_err[1]);
    fp_err = fdopen(pipe_err[0], "r");

    /* send quit command to nirt */
    sret = fwrite("q\n", 1, 2, fp_in);
    if (sret != 2)
	bu_log("fwrite failure\n");

    (void)fclose(fp_in);

#else
    memset((void *)&si, 0, sizeof(STARTUPINFO));
    memset((void *)&pi, 0, sizeof(PROCESS_INFORMATION));
    memset((void *)&sa, 0, sizeof(SECURITY_ATTRIBUTES));

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    /* Create a pipe for the child process's STDOUT. */
    CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0);

    /* Create noninheritable read handle and close the inheritable read handle. */
    DuplicateHandle(GetCurrentProcess(), pipe_out[0],
		    GetCurrentProcess(),  &pipe_outDup ,
		    0,  FALSE,
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_out[0]);

    /* Create a pipe for the child process's STDERR. */
    CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0);

    /* Create noninheritable read handle and close the inheritable read handle. */
    DuplicateHandle(GetCurrentProcess(), pipe_err[0],
		    GetCurrentProcess(),  &pipe_errDup ,
		    0,  FALSE,
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_err[0]);

    /* The steps for redirecting child process's STDIN:
     *     1.  Save current STDIN, to be restored later.
     *     2.  Create anonymous pipe to be STDIN for child process.
     *     3.  Set STDIN of the parent to be the read handle to the
     *         pipe, so it is inherited by the child process.
     *     4.  Create a noninheritable duplicate of the write handle,
     *         and close the inheritable write handle.
     */

    /* Create a pipe for the child process's STDIN. */
    CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0);

    /* Duplicate the write handle to the pipe so it is not inherited. */
    DuplicateHandle(GetCurrentProcess(), pipe_in[1],
		    GetCurrentProcess(), &pipe_inDup,
		    0, FALSE,                  /* not inherited */
		    DUPLICATE_SAME_ACCESS);
    CloseHandle(pipe_in[1]);

    si.cb = sizeof(STARTUPINFO);
    si.lpReserved = NULL;
    si.lpReserved2 = NULL;
    si.cbReserved2 = 0;
    si.lpDesktop = NULL;
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput   = pipe_in[0];
    si.hStdOutput  = pipe_out[1];
    si.hStdError   = pipe_err[1];
    si.wShowWindow = SW_HIDE;

    snprintf(line1, rem, "%s ", dgop->dgo_rt_cmd[0]);
    rem -= (int)strlen(line1) - 1;

    for (i = 1; i < dgop->dgo_rt_cmd_len; i++) {
	/* skip commands */
	if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL)
	    ++i;
	else {
	    /* append other arguments (i.e. options, file and obj(s)) */
	    snprintf(name, 1024, "\"%s\" ", dgop->dgo_rt_cmd[i]);
	    if (rem - strlen(name) < 1) {
		bu_log("Ran out of buffer space!");
		bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd");
		dgop->dgo_rt_cmd = NULL;
		return TCL_ERROR;
	    }
	    bu_strlcat(line1, name, sizeof(line1));
	    rem -= (int)strlen(name);
	}
    }

    CreateProcess(NULL, line1, NULL, NULL, TRUE,
		  DETACHED_PROCESS, NULL, NULL,
		  &si, &pi);

    /* use fp_in to feed view info to nirt */
    CloseHandle(pipe_in[0]);
    fp_in = _fdopen(_open_osfhandle((intptr_t)pipe_inDup, _O_TEXT), "wb");
    setmode(fileno(fp_in), O_BINARY);

    /* send commands down the pipe */
    for (i = 1; i < dgop->dgo_rt_cmd_len-2; i++)
	if (strstr(dgop->dgo_rt_cmd[i], "-e") != NULL)
	    fprintf(fp_in, "%s\n", dgop->dgo_rt_cmd[++i]);

    /* use fp_out to read back the result */
    CloseHandle(pipe_out[1]);
    fp_out = _fdopen(_open_osfhandle((intptr_t)pipe_outDup, _O_TEXT), "rb");
    setmode(fileno(fp_out), O_BINARY);

    /* use fp_err to read any error messages */
    CloseHandle(pipe_err[1]);
    fp_err = _fdopen(_open_osfhandle((intptr_t)pipe_errDup, _O_TEXT), "rb");
    setmode(fileno(fp_err), O_BINARY);

    /* send quit command to nirt */
    fwrite("q\n", 1, 2, fp_in);
    (void)fclose(fp_in);

#endif

    bu_vls_free(&p_vls);   /* use to form "partition" part of nirt command above */
    if (DG_QRAY_GRAPHICS(dgop)) {
	double scan[4];

	if (DG_QRAY_TEXT(dgop))
	    bu_vls_free(&o_vls); /* used to form "overlap" part of nirt command above */

	BU_LIST_INIT(&HeadQRayData.l);

	/* handle partitions */
	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) {
	    if (line[0] == '\n') {
		Tcl_AppendResult(dgop->interp, line+1, (char *)NULL);
		break;
	    }

	    BU_ALLOC(ndlp, struct dg_qray_dataList);
	    BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l);

	    if (sscanf(line, "%le %le %le %le",
		       &scan[0], &scan[1], &scan[2], &scan[3]) != 4)
		break;
	    ndlp->x_in = scan[0];
	    ndlp->y_in = scan[1];
	    ndlp->z_in = scan[2];
	    ndlp->los = scan[3];
	}

	vbp = rt_vlblock_init();
	dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 0);
	bu_list_free(&HeadQRayData.l);
	dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0);
	rt_vlblock_free(vbp);

	/* handle overlaps */
	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL) {
	    if (line[0] == '\n') {
		Tcl_AppendResult(dgop->interp, line+1, (char *)NULL);
		break;
	    }

	    BU_ALLOC(ndlp, struct dg_qray_dataList);
	    BU_LIST_APPEND(HeadQRayData.l.back, &ndlp->l);

	    if (sscanf(line, "%le %le %le %le",
		       &scan[0], &scan[1], &scan[2], &scan[3]) != 4)
		break;
	    ndlp->x_in = scan[0];
	    ndlp->y_in = scan[1];
	    ndlp->z_in = scan[2];
	    ndlp->los = scan[3];
	}
	vbp = rt_vlblock_init();
	dgo_qray_data_to_vlist(dgop, vbp, &HeadQRayData, dir, 1);
	bu_list_free(&HeadQRayData.l);
	dgo_cvt_vlblock_to_solids(dgop, vbp, bu_vls_addr(&dgop->dgo_qray_basename), 0);
	rt_vlblock_free(vbp);
    }

    /*
     * Notify observers, if any, before generating textual output since
     * such an act (observer notification) wipes out whatever gets stuffed
     * into the result.
     */
    dgo_notify(dgop);

    if (DG_QRAY_TEXT(dgop)) {
	bu_vls_free(&t_vls);

	while (bu_fgets(line, RT_MAXLINE, fp_out) != (char *)NULL)
	    Tcl_AppendResult(dgop->interp, line, (char *)NULL);
    }

    (void)fclose(fp_out);

    while (bu_fgets(line, RT_MAXLINE, fp_err) != (char *)NULL)
	Tcl_AppendResult(dgop->interp, line, (char *)NULL);
    (void)fclose(fp_err);


#ifndef _WIN32

    /* Wait for program to finish */
    while ((rpid = wait(&retcode)) != pid && rpid != -1)
	;	/* NULL */

    if (retcode != 0)
	pr_wait_status(dgop->interp, retcode);
#else
    /* Wait for program to finish */
    WaitForSingleObject(pi.hProcess, INFINITE);

#endif

    FOR_ALL_SOLIDS(sp, &dgop->dgo_headSolid)
	sp->s_wflag = DOWN;

    bu_free(dgop->dgo_rt_cmd, "free dgo_rt_cmd");
    dgop->dgo_rt_cmd = NULL;

    return TCL_OK;
}
static void
tree_solids(union tree *tp, struct tree_bark *tb, int op, struct resource *resp)
{
    RT_CK_TREE(tp);

    switch (tp->tr_op) {
	case OP_NOP:
	    return;

	case OP_SOLID: {
	    struct reg_db_internals *dbint;
	    matp_t mp;
	    long sol_id = 0;
	    struct rt_ell_internal *ell_p;
	    vect_t v;
	    int ret;

	    BU_ALLOC(dbint, struct reg_db_internals);
	    BU_LIST_INIT_MAGIC(&(dbint->l), DBINT_MAGIC);

	    if (tp->tr_a.tu_stp->st_matp)
		mp = tp->tr_a.tu_stp->st_matp;
	    else
		mp = (matp_t)bn_mat_identity;

	    /* Get the internal form of this solid & add it to the list */
	    ret = rt_db_get_internal(&dbint->ip, tp->tr_a.tu_stp->st_dp, tb->dbip, mp, resp);
	    if (ret < 0) {
		bu_log("Failure reading %s object from database.\n", OBJ[sol_id].ft_name);
		return;
	    }

	    RT_CK_DB_INTERNAL(&dbint->ip);
	    dbint->st_p = tp->tr_a.tu_stp;

	    sol_id = dbint->ip.idb_type;

	    if (sol_id < 0) {
		bu_log("Primitive ID %ld out of bounds\n", sol_id);
		bu_bomb("");
	    }


	    if (sol_id != ID_ELL) {

		if (op == OP_UNION)
		    bu_log("Non-ellipse \"union\" primitive of \"%s\" being ignored\n",
			   tb->name);

		if (rdebug&RDEBUG_SHADE)
		    bu_log(" got a primitive type %ld \"%s\".  This primitive ain't no ellipse bucko!\n",
			   sol_id, OBJ[sol_id].ft_name);

		break;
	    }


	    ell_p = (struct rt_ell_internal *)dbint->ip.idb_ptr;

	    if (rdebug&RDEBUG_SHADE)
		bu_log(" got a primitive type %ld \"%s\"\n",
		       sol_id,
		       OBJ[sol_id].ft_name);

	    RT_ELL_CK_MAGIC(ell_p);

	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("point", ell_p->v);
		VPRINT("a", ell_p->a);
		VPRINT("b", ell_p->b);
		VPRINT("c", ell_p->c);
	    }

	    /* create the matrix that maps the coordinate system defined
	     * by the ellipse into model space, and get inverse for use
	     * in the _render() proc
	     */
	    MAT_IDN(mp);
	    VMOVE(v, ell_p->a);	VUNITIZE(v);
	    mp[0] = v[0];	mp[4] = v[1];	mp[8] = v[2];

	    VMOVE(v, ell_p->b);	VUNITIZE(v);
	    mp[1] = v[0];	mp[5] = v[1];	mp[9] = v[2];

	    VMOVE(v, ell_p->c);	VUNITIZE(v);
	    mp[2] = v[0];	mp[6] = v[1];	mp[10] = v[2];

	    MAT_DELTAS_VEC(mp, ell_p->v);

	    MAT_COPY(dbint->ell2model, mp);
	    bn_mat_inv(dbint->model2ell, mp);


	    /* find scaling of gaussian puff in ellipsoid space */
	    VSET(dbint->one_sigma,
		 MAGNITUDE(ell_p->a) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->b) / tb->gs->gauss_sigma,
		 MAGNITUDE(ell_p->c) / tb->gs->gauss_sigma);


	    if (rdebug&RDEBUG_SHADE) {
		VPRINT("sigma", dbint->one_sigma);
	    }
	    BU_LIST_APPEND(tb->l, &(dbint->l));

	    break;
	}
	case OP_UNION:
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    break;

	case OP_NOT: bu_log("Warning: 'Not' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_GUARD:bu_log("Warning: 'Guard' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;
	case OP_XNOP:bu_log("Warning: 'XNOP' region operator in %s\n", tb->name);
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    break;

	case OP_INTERSECT:
	case OP_SUBTRACT:
	case OP_XOR:
	    /* XXX this can get us in trouble if 1 solid is subtracted
	     * from less than all the "union" solids of the region.
	     */
	    tree_solids(tp->tr_b.tb_left, tb, tp->tr_op, resp);
	    tree_solids(tp->tr_b.tb_right, tb, tp->tr_op, resp);
	    return;

	default:
	    bu_bomb("rt_tree_region_assign: bad op\n");
    }
}
Exemplo n.º 25
0
/**
 * Split a NURB curve by inserting a multiple knot and return the
 * result of the two curves.
 *
 * Algorithm
 *
 * Insert a multiple knot of the curve order.  If internal knot values
 * exist than pick the one closest to the middle and add additional
 * knots to split at that value, otherwise add multiple knots at the
 * mid point of the knot vector. Use the new knot vector to pass to
 * the oslo refinement process and split the curve.  Separate the
 * curve and return the two resulting curves.
 *
 * The original curve is undisturbed by this operation.
 */
void
rt_nurb_c_split(struct bu_list *split_hd, const struct edge_g_cnurb *crv)
{
    struct knot_vector new_kv;
    fastf_t value;
    struct oslo_mat * oslo;
    int i;
    int k_index = 0;
    struct edge_g_cnurb * crv1, * crv2;
    int coords;

    NMG_CK_CNURB(crv);

    coords = RT_NURB_EXTRACT_COORDS(crv->pt_type),

    value = crv->k.knots[(crv->k.k_size -1)/2];

    for (i = 0; i < crv->k.k_size; i++)
        if (ZERO(value - crv->k.knots[i])) {
            k_index = i;
            break;
        }
    if (k_index == 0) {
        value = (value +
                 crv->k.knots[ crv->k.k_size -1])
                /2.0;
        k_index = crv->order;
    }

    rt_nurb_kvmult(&new_kv, &crv->k, crv->order, value, (struct resource *)NULL);

    oslo = (struct oslo_mat *)
           rt_nurb_calc_oslo(crv->order, &crv->k, &new_kv, (struct resource *)NULL);

    GET_CNURB(crv1);
    crv1->order  = crv->order;
    rt_nurb_kvextract(&crv1->k, &new_kv, 0, k_index + crv->order, (struct resource *)NULL);
    crv1->pt_type = crv->pt_type;
    crv1->c_size = crv1->k.k_size - crv1->order;
    crv1->ctl_points = (fastf_t *)
                       bu_malloc(sizeof(fastf_t) * crv1->c_size *
                                 RT_NURB_EXTRACT_COORDS(crv1->pt_type),
                                 "rt_nurb_c_split: crv1 control points");

    GET_CNURB(crv2);
    crv2->order  = crv->order;
    rt_nurb_kvextract(&crv2->k, &new_kv, k_index, new_kv.k_size, (struct resource *)NULL);
    crv2->pt_type = crv->pt_type;
    crv2->c_size = crv2->k.k_size - crv2->order;
    crv2->ctl_points = (fastf_t *)
                       bu_malloc(sizeof(fastf_t) * crv2->c_size *
                                 RT_NURB_EXTRACT_COORDS(crv2->pt_type),
                                 "rt_nurb_s_split: crv2 mesh control points");

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv1->ctl_points,
                     coords, coords, 0, k_index, crv->pt_type);

    rt_nurb_map_oslo(oslo, crv->ctl_points, crv2->ctl_points,
                     coords, coords, k_index, new_kv.k_size - crv2->order,
                     crv2->pt_type);

    rt_nurb_free_oslo(oslo, (struct resource *)NULL);

    bu_free((char *) new_kv.knots, "rt_nurb_c_split; new_kv.knots");

    /* Arrangement will be:  head, crv1, crv2 */
    BU_LIST_APPEND(split_hd, &crv2->l);
    BU_LIST_APPEND(split_hd, &crv1->l);
}
Exemplo n.º 26
0
/**
 * Algorithm
 *
 * Given a parametric direction (u or v) look at the direction knot
 * vector and insert a multiple knot of parametric direction surface
 * order.  If internal knot values exist than pick the one closest to
 * the middle and add additional knots to split at that value,
 * otherwise add multiple knots at the mid point of the knot
 * vector. Use the new knot vector to pass to the oslo refinement
 * process and split the surface.  Separate the surface and return the
 * two resulting surface.
 *
 * The original surface is undisturbed by this operation.
 */
void
rt_nurb_s_split(struct bu_list *split_hd, const struct face_g_snurb *srf, int dir, struct resource *res)
{
    struct knot_vector new_kv;
    fastf_t value;
    struct oslo_mat * oslo;
    int i;
    int k_index = 0;
    struct face_g_snurb * srf1, * srf2;

    NMG_CK_SNURB(srf);

    if (dir == RT_NURB_SPLIT_ROW) {
        value = srf->u.knots[(srf->u.k_size -1)/2];

        for (i = 0; i < srf->u.k_size; i++)
            if (ZERO(value - srf->u.knots[i])) {
                k_index = i;
                break;
            }
        if (k_index == 0) {
            value = (value +
                     srf->u.knots[ srf->u.k_size -1])
                    /2.0;
            k_index = srf->order[0];
        }

        rt_nurb_kvmult(&new_kv, &srf->u, srf->order[0], value, res);

        oslo = (struct oslo_mat *)
               rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_ROW], &srf->u, &new_kv, res);

        GET_SNURB(srf1);
        srf1->order[0]  = srf->order[0];
        srf1->order[1]  = srf->order[1];
        srf1->dir = RT_NURB_SPLIT_ROW;
        rt_nurb_kvextract(&srf1->u, &new_kv, 0, k_index + srf1->order[0], res);
        rt_nurb_kvcopy(&srf1->v, &srf->v, res);

        srf1->pt_type = srf->pt_type;
        srf1->s_size[0] = srf1->v.k_size -
                          srf1->order[1];
        srf1->s_size[1] = srf1->u.k_size -
                          srf1->order[0];

        srf1->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
                                     srf1->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                                     "rt_nurb_s_split: srf1 row mesh control points");

        GET_SNURB(srf2);
        srf2->order[0]  = srf->order[0];
        srf2->order[1]  = srf->order[1];
        srf2->dir = RT_NURB_SPLIT_ROW;
        rt_nurb_kvextract(&srf2->u, &new_kv, k_index, new_kv.k_size, res);
        rt_nurb_kvcopy(&srf2->v, &srf->v, res);

        srf2->pt_type = srf->pt_type;
        srf2->s_size[0] = srf2->v.k_size -
                          srf2->order[1];
        srf2->s_size[1] = srf2->u.k_size -
                          srf2->order[0];

        srf2->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
                                     srf2->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                                     "rt_nurb_s_split: srf2 row mesh control points");

        for (i = 0; i < srf->s_size[0]; i++) {
            fastf_t * old_mesh_ptr;
            fastf_t * new_mesh_ptr;

            old_mesh_ptr = &srf->ctl_points[
                               i * srf->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf->pt_type)];
            new_mesh_ptr = &srf1->ctl_points[
                               i * srf1->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                             0, k_index, srf1->pt_type);
            new_mesh_ptr = &srf2->ctl_points[
                               i * srf2->s_size[1] *
                               RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                             k_index, new_kv.k_size - srf2->order[0],
                             srf2->pt_type);
        }
    } else {
        value = srf->v.knots[(srf->v.k_size -1)/2];

        for (i = 0; i < srf->v.k_size; i++)
            if (ZERO(value - srf->v.knots[i])) {
                k_index = i;
                break;
            }
        if (k_index == 0) {
            value = (value +
                     srf->v.knots[ srf->v.k_size -1])
                    /2.0;
            k_index = srf->order[1];
        }

        rt_nurb_kvmult(&new_kv, &srf->v, srf->order[RT_NURB_SPLIT_COL], value, res);

        oslo = (struct oslo_mat *)
               rt_nurb_calc_oslo(srf->order[RT_NURB_SPLIT_COL], &srf->v, &new_kv, res);

        GET_SNURB(srf1);
        srf1->order[0]  = srf->order[0];
        srf1->order[1]  = srf->order[1];
        srf1->dir = RT_NURB_SPLIT_COL;
        rt_nurb_kvextract(&srf1->v, &new_kv, 0, k_index + srf1->order[RT_NURB_SPLIT_COL], res);
        rt_nurb_kvcopy(&srf1->u, &srf->u, res);

        srf1->pt_type = srf->pt_type;
        srf1->s_size[0] = srf1->v.k_size -
                          srf1->order[1];
        srf1->s_size[1] = srf1->u.k_size -
                          srf1->order[0];

        srf1->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf1->s_size[0] *
                                     srf1->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                                     "rt_nurb_s_split: srf1 col mesh control points");

        GET_SNURB(srf2);
        srf2->order[0]  = srf->order[0];
        srf2->order[1]  = srf->order[1];
        srf2->dir = RT_NURB_SPLIT_COL;
        rt_nurb_kvextract(&srf2->v, &new_kv, k_index, new_kv.k_size, res);
        rt_nurb_kvcopy(&srf2->u, &srf->u, res);

        srf2->pt_type = srf->pt_type;
        srf2->s_size[0] = srf2->v.k_size -
                          srf2->order[1];
        srf2->s_size[1] = srf2->u.k_size -
                          srf2->order[0];

        srf2->ctl_points = (fastf_t *)
                           bu_malloc(sizeof(fastf_t) * srf2->s_size[0] *
                                     srf2->s_size[1] *
                                     RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                                     "rt_nurb_s_split: srf2 col mesh control points");

        for (i = 0; i < srf->s_size[1]; i++) {
            fastf_t * old_mesh_ptr;
            fastf_t * new_mesh_ptr;

            old_mesh_ptr = &srf->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf->pt_type)];
            new_mesh_ptr = &srf1->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf1->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             srf->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             srf1->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf1->pt_type),
                             0, k_index, srf1->pt_type);
            new_mesh_ptr = &srf2->ctl_points[
                               i * RT_NURB_EXTRACT_COORDS(srf2->pt_type)];
            rt_nurb_map_oslo(oslo, old_mesh_ptr, new_mesh_ptr,
                             srf->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf->pt_type),
                             srf2->s_size[1] *
                             RT_NURB_EXTRACT_COORDS(srf2->pt_type),
                             k_index, new_kv.k_size - srf2->order[1],
                             srf2->pt_type);
        }
    }

    /* Arrangement will be:  head, srf1, srf2 */
    BU_LIST_APPEND(split_hd, &srf2->l);
    BU_LIST_APPEND(split_hd, &srf1->l);

    rt_nurb_free_oslo(oslo, res);
    bu_free((char *)new_kv.knots, "rt_nurb_s_split: new kv knots");

}